Skip to content

symfonic.knowledge.adapters.chroma

chroma

ChromaKnowledgeProvider -- RAG adapter for local ChromaDB collections.

Requires the knowledge optional dependency group::

pip install symfonic-core[knowledge]

All sync ChromaDB calls are wrapped with asyncio.to_thread for non-blocking operation in async contexts.

ChromaKnowledgeProvider

ChromaKnowledgeProvider(path: str, collection_name: str)

KnowledgeProvider backed by a local ChromaDB persistent collection.

Connects to an existing ChromaDB directory and queries a named collection using ChromaDB's built-in default embedding function. For custom embeddings, pre-embed queries externally and use a different adapter.

All synchronous ChromaDB operations are wrapped with asyncio.to_thread.

Parameters:

Name Type Description Default
path str

Filesystem path to the ChromaDB persistent directory.

required
collection_name str

Name of the collection to query.

required

Example::

provider = ChromaKnowledgeProvider(
    path="/data/chroma",
    collection_name="legal_docs",
)
fragments = await provider.search("force majeure clause", limit=5)
Source code in src/symfonic/knowledge/adapters/chroma.py
def __init__(
    self,
    path: str,
    collection_name: str,
) -> None:
    self._path = path
    self._collection_name = collection_name
    self._client = chromadb.PersistentClient(path=path)
    self._collection = self._client.get_or_create_collection(
        name=collection_name,
        metadata={"hnsw:space": "cosine"},
    )

collection_info async

collection_info() -> dict[str, Any]

Return collection metadata.

Returns:

Type Description
dict[str, Any]

Dict with name, path, and count keys.

Source code in src/symfonic/knowledge/adapters/chroma.py
async def collection_info(self) -> dict[str, Any]:
    """Return collection metadata.

    Returns:
        Dict with ``name``, ``path``, and ``count`` keys.
    """
    count: int = await asyncio.to_thread(self._collection.count)
    return {
        "name": self._collection_name,
        "path": self._path,
        "count": count,
    }

search async

search(
    query: str, limit: int = 3
) -> list[KnowledgeFragment]

Query the collection using ChromaDB's built-in embedding.

Parameters:

Name Type Description Default
query str

Natural language search query.

required
limit int

Maximum number of fragments to return.

3

Returns:

Type Description
list[KnowledgeFragment]

List of KnowledgeFragment sorted by descending score.

Source code in src/symfonic/knowledge/adapters/chroma.py
async def search(
    self,
    query: str,
    limit: int = 3,
) -> list[KnowledgeFragment]:
    """Query the collection using ChromaDB's built-in embedding.

    Args:
        query: Natural language search query.
        limit: Maximum number of fragments to return.

    Returns:
        List of KnowledgeFragment sorted by descending score.
    """
    results: dict[str, Any] = await asyncio.to_thread(
        self._collection.query,
        query_texts=[query],
        n_results=limit,
    )

    fragments: list[KnowledgeFragment] = []
    if results and results.get("ids"):
        ids: list[str] = results["ids"][0]
        distances: list[float] = results.get("distances", [[]])[0]
        documents: list[str] = results.get("documents", [[]])[0]
        metadatas: list[dict[str, Any]] = results.get("metadatas", [[]])[0]

        for i, doc_id in enumerate(ids):
            score = 1.0 - distances[i] if i < len(distances) else 0.0
            doc = documents[i] if i < len(documents) else ""
            meta: dict[str, Any] = metadatas[i] if i < len(metadatas) else {}
            source: str = meta.get("source", doc_id)

            fragments.append(
                KnowledgeFragment(
                    content=doc,
                    source=source,
                    score=round(score, 4),
                    metadata=meta,
                )
            )

    return sorted(fragments, key=lambda f: f.score, reverse=True)