feat: solution for 'Экзамен: RAG-агент с ChromaDB и веб-поиском'

This commit is contained in:
2026-07-01 13:31:25 +03:00
parent 32da3933de
commit dc4f151b3d
8 changed files with 410 additions and 318 deletions
+28 -39
View File
@@ -1,54 +1,43 @@
**What was implemented**
The script `src/index.py` now uses **ChromaDB** as the persistent vector store instead of Qdrant.
It loads documents from a folder, splits them into chunks, embeds them with OpenAI embeddings, and stores the vectors in a Chroma collection.
A RetrievalQA chain is built with LangChains `RetrievalQA` and OpenAIs GPT model, and a lightweight websearch tool (`DuckDuckGoSearchRun`) is kept for quick queries.
- Replaced the previous Qdrantbased vector store with a lightweight wrapper around **ChromaDB** (`src/vector_store.py`).
- Updated the `RAGAgent` to work exclusively with the new `ChromaVectorStore`.
- Kept the FastAPI endpoints (`/ingest`, `/query`, `/websearch`) unchanged, so the public API and websearch logic remain intact.
- Removed every import and reference to Qdrant, ensuring the stack now matches the assignment.
**Why the main parts satisfy the assignment**
* The vector database is explicitly ChromaDB the `initialize_vectorstore()` function creates a `chromadb.PersistentClient` and wraps it with LangChains `Chroma` wrapper.
* All required stack components are present: `chromadb`, `langchain`, `openai`, and `python-dotenv`.
* The agent can ingest, query, and perform web search, matching the functional requirements of the exam task.
**Why the main parts satisfy the requirements**
- `ChromaVectorStore` creates a Chroma client and a collection, then exposes `add_documents` and `similarity_search` that match the original Qdrant interface.
- `RAGAgent` uses this store for ingestion and querying, and still relies on OpenAI embeddings, so the RAG workflow is preserved.
- The FastAPI app simply forwards requests to the agent; no Qdrant code is touched, so the vector database is now exclusively ChromaDB.
- Websearch utilities (`src/web_search.py`) are untouched, so the searchtoingest pipeline continues to work.
**Key code excerpts**
`src/index.py` imports and vector store initialization
`src/vector_store.py` Chroma client and collection creation
```python
import chromadb
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
...
def initialize_vectorstore() -> Chroma:
client = chromadb.PersistentClient(path=CHROMA_DB_PATH)
client.get_or_create_collection(name=COLLECTION_NAME)
vectorstore = Chroma(
client=client,
collection_name=COLLECTION_NAME,
embedding_function=OpenAIEmbeddings(model=EMBEDDING_MODEL),
)
return vectorstore
self.client = chromadb.Client()
self.collection = self.client.get_or_create_collection(name=collection_name)
```
`src/index.py` ingesting documents into Chroma
`src/rag_agent.py` ingestion uses the new store
```python
def ingest_documents(folder_path: str, vectorstore: Chroma) -> None:
raw_texts = load_documents_from_folder(folder_path)
chunks = split_text(raw_texts)
vectorstore.add_texts(chunks)
print(f"Ingested {len(chunks)} chunks into collection '{COLLECTION_NAME}'.")
self.vector_store.add_documents(docs_with_embeddings)
```
`src/index.py` websearch helper
`src/main.py` FastAPI endpoint that calls the agent
```python
def perform_web_search(query: str) -> List[Dict[str, str]]:
search_tool = DuckDuckGoSearchRun()
results = search_tool.run(query)
if isinstance(results, list):
return results
return [{"title": "Search Result", "url": "", "body": results}]
@app.post("/ingest")
def ingest(request: IngestRequest):
docs = [doc.dict() for doc in request.documents]
rag_agent.ingest(docs)
```
**Limitations**
* No unit tests are included.
* Error handling is minimal (e.g., missing environment variables or empty folders).
* The script is singlethreaded and may not scale for very large corpora without further optimization.
`src/web_search.py` still feeds results into the agent
```python
agent.ingest(docs_to_ingest)
```
Overall, the implementation now adheres to the required stack and fulfills the RAG agent functionality described in the assignment.
**Honest limitations**
- ChromaDB is used in its default inmemory mode; data will not persist across server restarts unless a persistent storage path is configured.
- No additional error handling for Chroma connection failures has been added beyond the basic try/except in the API routes.
Overall, the project now uses only ChromaDB for vector storage, keeps all existing functionality, and respects the assignment constraints.