Skip to content
Merged

Dev #69

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
959b0b3
refactor(rust): remove redundant clippy attributes and cleanup module…
zTgx Apr 15, 2026
d71e501
refactor(rust): remove unused fields and methods from index context
zTgx Apr 15, 2026
5e43243
refactor(client): remove unused indexer configuration and add validation
zTgx Apr 15, 2026
5f4cee7
refactor: remove workspace parameter from Engine constructor
zTgx Apr 15, 2026
5e05d6a
refactor(utils): remove unused format and timing modules, add fingerp…
zTgx Apr 15, 2026
03820a0
refactor(rust): migrate to centralized LlmPool configuration system
zTgx Apr 15, 2026
071c5fd
feat(pipeline): inject shared LLM client into pipeline context
zTgx Apr 15, 2026
df2557a
refactor(rust): consolidate EventEmitter imports to use crate::events
zTgx Apr 15, 2026
32d81bb
refactor(index-context): consolidate directory indexing methods into …
zTgx Apr 15, 2026
d08dd9c
feat: add source_path field and update query context API
zTgx Apr 15, 2026
04ff699
refactor(docs): update QueryContext API usage to use with_doc_ids ins…
zTgx Apr 15, 2026
ececf51
refactor(python): remove StrategyPreference class and related methods
zTgx Apr 15, 2026
3115ac9
refactor(engine): add TODO comment for parallelizing document queries
zTgx Apr 15, 2026
935a238
docs(readme): remove workspace parameter from Engine initialization e…
zTgx Apr 15, 2026
17cdf8b
refactor(client): remove unused EventEmitter re-export
zTgx Apr 15, 2026
f9ed739
docs: remove deprecated workspace parameter and strategy preferences
zTgx Apr 15, 2026
e310de6
feat(index): add pipeline checkpoint functionality for resumable inde…
zTgx Apr 15, 2026
893bda9
feat(python-sdk): update SDK with QueryContext and enhanced indexing …
zTgx Apr 15, 2026
97698ab
feat(rust): update project description to better reflect AI focus
zTgx Apr 15, 2026
0582f2b
chore(release): bump workspace and package versions
zTgx Apr 15, 2026
1ae34d8
chore(release): add GitHub Actions workflow for automated releases
zTgx Apr 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Release

on:
push:
tags:
- 'v*'

env:
CARGO_TERM_COLOR: always

jobs:
# Publish Rust crate to crates.io
publish-crates:
name: Publish to crates.io
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Publish vectorless crate
run: cargo publish -p vectorless
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

# Publish Python package to PyPI
publish-pypi:
name: Publish to PyPI
runs-on: ubuntu-latest
permissions:
id-token: write # Trusted Publishers
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: pyo3/maturin-action@v1
with:
command: publish
args: --skip-existing
maturin-version: latest

# Create GitHub Release
github-release:
name: GitHub Release
runs-on: ubuntu-latest
needs: [publish-crates, publish-pypi]
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Extract version from tag
id: version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: Release ${{ steps.version.outputs.VERSION }}
generate_release_notes: true
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["rust", "python"]
resolver = "2"

[workspace.package]
version = "0.1.27"
version = "0.1.28"
edition = "2024"
authors = ["zTgx <beautifularea@gmail.com>"]
license = "Apache-2.0"
Expand Down
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ from vectorless import Engine, IndexContext
async def main():
# Create engine — api_key and model are required
engine = Engine(
workspace="./data",
api_key="sk-...",
model="gpt-4o",
)
Expand Down Expand Up @@ -63,7 +62,6 @@ use vectorless::client::{EngineBuilder, IndexContext, QueryContext};
#[tokio::main]
async fn main() -> vectorless::Result<()> {
let engine = EngineBuilder::new()
.with_workspace("./data")
.with_key("sk-...")
.with_model("gpt-4o")
.build()
Expand All @@ -75,7 +73,7 @@ async fn main() -> vectorless::Result<()> {

// Query
let result = engine.query(
QueryContext::new("What is the total revenue?").with_doc_id(doc_id)
QueryContext::new("What is the total revenue?").with_doc_ids(vec![doc_id.to_string()])
).await?;
println!("Answer: {}", result.content);

Expand Down
4 changes: 1 addition & 3 deletions docs/blog/2026-04-12-welcome/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ from vectorless import Engine, IndexContext

async def main():
engine = Engine(
workspace="./data",
api_key="sk-...",
model="gpt-4o",
)
Expand All @@ -53,7 +52,6 @@ use vectorless::{EngineBuilder, IndexContext, QueryContext};
#[tokio::main]
async fn main() -> vectorless::Result<()> {
let engine = EngineBuilder::new()
.with_workspace("./data")
.with_key("sk-...")
.with_model("gpt-4o")
.build()
Expand All @@ -63,7 +61,7 @@ async fn main() -> vectorless::Result<()> {
let doc_id = result.doc_id().unwrap();

let result = engine.query(
QueryContext::new("What is the total revenue?").with_doc_id(doc_id)
QueryContext::new("What is the total revenue?").with_doc_ids(vec![doc_id.to_string()])
).await?;
println!("{}", result.content);

Expand Down
2 changes: 0 additions & 2 deletions docs/docs/examples/batch-indexing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ from vectorless import Engine, IndexContext, IndexOptions

async def main():
engine = Engine(
workspace="./workspace",
api_key="sk-...",
model="gpt-4o",
)
Expand Down Expand Up @@ -53,7 +52,6 @@ use vectorless::client::{Engine, EngineBuilder, IndexContext};
#[tokio::main]
async fn main() -> vectorless::Result<()> {
let engine = EngineBuilder::new()
.with_workspace("./workspace")
.with_key("sk-...")
.with_model("gpt-4o")
.build()
Expand Down
5 changes: 1 addition & 4 deletions docs/docs/examples/multi-document.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ Query across multiple indexed documents using the cross-document strategy with g
import asyncio
from vectorless import (
Engine, IndexContext, QueryContext,
IndexOptions, StrategyPreference
IndexOptions,
)

async def main():
engine = Engine(
workspace="./workspace",
api_key="sk-...",
model="gpt-4o",
)
Expand All @@ -44,7 +43,6 @@ async def main():
result = await engine.query(
QueryContext("Compare quarterly revenue trends")
.with_doc_ids(doc_ids)
.with_strategy(StrategyPreference.CROSS_DOCUMENT)
)

for item in result.items:
Expand All @@ -54,7 +52,6 @@ async def main():
# Or query entire workspace
result = await engine.query(
QueryContext("What documents discuss risk factors?")
.with_workspace()
)

print(f"\nFound in {len(result.items)} document(s)")
Expand Down
12 changes: 4 additions & 8 deletions docs/docs/examples/quick-query.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ This example demonstrates the basic index-and-query workflow with both Python an

```python
import asyncio
from vectorless import Engine, IndexContext, QueryContext, StrategyPreference
from vectorless import Engine, IndexContext, QueryContext

async def main():
# 1. Create engine
engine = Engine(
workspace="./data",
api_key="sk-...",
model="gpt-4o",
)
Expand All @@ -28,16 +27,14 @@ async def main():
# 3. Simple keyword query
answer = await engine.query(
QueryContext("revenue")
.with_doc_id(doc_id)
.with_strategy(StrategyPreference.KEYWORD)
.with_doc_ids([doc_id])
)
print(f"Keyword result: {answer.single().content[:200]}")

# 4. Complex reasoning query
answer = await engine.query(
QueryContext("What are the main factors affecting performance?")
.with_doc_id(doc_id)
.with_strategy(StrategyPreference.HYBRID)
.with_doc_ids([doc_id])
)
print(f"Score: {answer.single().score:.2f}")
print(f"Hybrid result: {answer.single().content[:200]}")
Expand All @@ -58,7 +55,6 @@ use vectorless::StrategyPreference;
async fn main() -> vectorless::Result<()> {
// 1. Create engine
let engine = EngineBuilder::new()
.with_workspace("./data")
.with_key("sk-...")
.with_model("gpt-4o")
.build()
Expand All @@ -72,7 +68,7 @@ async fn main() -> vectorless::Result<()> {
// 3. Query with hybrid strategy
let answer = engine.query(
QueryContext::new("What are the main factors affecting performance?")
.with_doc_id(&doc_id)
.with_doc_ids(vec![doc_id.clone()])
).await?;

if let Some(item) = answer.single() {
Expand Down
8 changes: 3 additions & 5 deletions docs/docs/features/cross-document-graph.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,13 @@ When using the cross-document strategy, the graph boosts scores for connected do
4. Re-rank the merged result set

```python
from vectorless import Engine, QueryContext, StrategyPreference
from vectorless import Engine, QueryContext

engine = Engine(workspace="./data", api_key="sk-...", model="gpt-4o")
engine = Engine(api_key="sk-...", model="gpt-4o")

# Query across all documents with graph boosting
result = await engine.query(
QueryContext("Compare the approaches").with_strategy(
StrategyPreference.CROSS_DOCUMENT
)
QueryContext("Compare the approaches")
)
```

Expand Down
4 changes: 2 additions & 2 deletions docs/docs/features/pdf-support.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ Vectorless supports PDF documents with full page-level tracking and hierarchical
```python
from vectorless import Engine, IndexContext

engine = Engine(workspace="./data", api_key="sk-...", model="gpt-4o")
engine = Engine(api_key="sk-...", model="gpt-4o")

# Index a PDF
result = await engine.index(IndexContext.from_path("./report.pdf"))
doc_id = result.doc_id

# Query the PDF
answer = await engine.query(
QueryContext("What is discussed on page 5?").with_doc_id(doc_id)
QueryContext("What is discussed on page 5?").with_doc_ids([doc_id])
)
print(answer.single().content)
```
Expand Down
7 changes: 2 additions & 5 deletions docs/docs/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ from vectorless import Engine, IndexContext, QueryContext
async def main():
# Create an engine
engine = Engine(
workspace="./data",
api_key="sk-...",
model="gpt-4o",
)
Expand All @@ -38,7 +37,7 @@ async def main():

# Query the document
answer = await engine.query(
QueryContext("What is the total revenue?").with_doc_id(doc_id)
QueryContext("What is the total revenue?").with_doc_ids([doc_id])
)
print(answer.single().content)

Expand All @@ -49,7 +48,6 @@ asyncio.run(main())

```python
engine = Engine(
workspace="./data",
api_key="sk-...",
model="gpt-4o",
endpoint="https://api.your-provider.com/v1",
Expand All @@ -75,7 +73,6 @@ use vectorless::{EngineBuilder, IndexContext, QueryContext};
#[tokio::main]
async fn main() -> vectorless::Result<()> {
let engine = EngineBuilder::new()
.with_workspace("./data")
.with_key("sk-...")
.with_model("gpt-4o")
.build()
Expand All @@ -85,7 +82,7 @@ async fn main() -> vectorless::Result<()> {
let doc_id = result.doc_id().unwrap();

let result = engine.query(
QueryContext::new("What is the total revenue?").with_doc_id(doc_id)
QueryContext::new("What is the total revenue?").with_doc_ids(vec![doc_id.to_string()])
).await?;

if let Some(item) = result.single() {
Expand Down
4 changes: 1 addition & 3 deletions docs/docs/intro.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ from vectorless import Engine, IndexContext

async def main():
engine = Engine(
workspace="./data",
api_key="sk-...",
model="gpt-4o",
)
Expand All @@ -55,7 +54,6 @@ use vectorless::{EngineBuilder, IndexContext, QueryContext};
#[tokio::main]
async fn main() -> vectorless::Result<()> {
let engine = EngineBuilder::new()
.with_workspace("./data")
.with_key("sk-...")
.with_model("gpt-4o")
.build()
Expand All @@ -65,7 +63,7 @@ async fn main() -> vectorless::Result<()> {
let doc_id = result.doc_id().unwrap();

let result = engine.query(
QueryContext::new("What is the total revenue?").with_doc_id(doc_id)
QueryContext::new("What is the total revenue?").with_doc_ids(vec![doc_id.to_string()])
).await?;
println!("{}", result.content);

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/retrieval/search-algorithms.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ from vectorless import QueryContext

ctx = (
QueryContext("complex multi-hop question")
.with_doc_id(doc_id)
.with_doc_ids([doc_id])
.with_depth_limit(10) # Max tree traversal depth
.with_max_tokens(4000) # Max tokens in result
)
Expand Down
20 changes: 6 additions & 14 deletions docs/docs/retrieval/strategies.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,9 @@ Vectorless provides five retrieval strategies, each designed for different query
Fast TF-IDF/BM25 matching against the pre-computed reasoning index. No LLM calls during search.

```python
from vectorless import QueryContext, StrategyPreference
from vectorless import QueryContext

ctx = QueryContext("revenue").with_doc_id(doc_id).with_strategy(
StrategyPreference.KEYWORD
)
ctx = QueryContext("revenue").with_doc_ids([doc_id])
```

Use when:
Expand All @@ -38,9 +36,7 @@ Use when:
LLM-powered tree navigation with full contextual understanding. The LLM sees the table of contents, node summaries, and makes navigation decisions at each level.

```python
ctx = QueryContext("Explain the relationship between architecture and performance").with_doc_id(doc_id).with_strategy(
StrategyPreference.LLM
)
ctx = QueryContext("Explain the relationship between architecture and performance").with_doc_ids([doc_id])
```

Use when:
Expand All @@ -53,9 +49,7 @@ Use when:
Two-phase retrieval: BM25 pre-filter followed by LLM refinement. Combines the speed of keyword matching with the accuracy of LLM reasoning.

```python
ctx = QueryContext("What are the growth trends?").with_doc_id(doc_id).with_strategy(
StrategyPreference.HYBRID
)
ctx = QueryContext("What are the growth trends?").with_doc_ids([doc_id])
```

The recommended default for most queries. Fast pre-filtering reduces the number of nodes sent to the LLM, keeping token costs manageable while maintaining high accuracy.
Expand All @@ -65,16 +59,14 @@ The recommended default for most queries. Fast pre-filtering reduces the number
Searches across multiple indexed documents and aggregates results. Uses the cross-document relationship graph for score boosting.

```python
ctx = QueryContext("Compare the architectures").with_strategy(
StrategyPreference.CROSS_DOCUMENT
)
ctx = QueryContext("Compare the architectures")
```

When a high-confidence result is found in one document, neighbor documents in the graph receive a score boost, surfacing related content across the workspace.

## Auto Selection

When using `StrategyPreference.AUTO` (default), the engine analyzes query complexity and selects the appropriate strategy:
By default, the engine analyzes query complexity and automatically selects the appropriate strategy:

- Simple keyword queries → Keyword strategy
- Complex reasoning queries → Hybrid strategy
Expand Down
Loading