feat: solution for 'Повторный экзамен: FAQ-бот — ChromaDB + один MCP-tool'

This commit is contained in:
2026-07-01 15:14:37 +03:00
parent 51ab1df383
commit b17c7be620
6 changed files with 334 additions and 110 deletions
+41 -34
View File
@@ -1,42 +1,49 @@
**Что реализовано**
- В проекте теперь используется **только ChromaDB** как векторное хранилище.
- Для генерации эмбеддингов применён **единственный MCP‑tool**.
- Все остальные импорты векторных библиотек удалены, оставлены только `chromadb` и `mcp-tool`.
**What was implemented**
- Unified the vectorstorage layer to a single stack: **ChromaDB** as the vector database and **MCPtool** as the sole embedding generator.
- Removed all previous references to other vector stores (e.g. FAISS, Pinecone).
- Kept the FAQbot logic unchanged, so the interactive questionanswer loop still works.
**Почему это соответствует требованиям**
- В `package.json` остались только зависимости `chromadb` и `mcp-tool`, что гарантирует отсутствие других хранилищ.
- В `src/vectorStore.js` создаётся один экземпляр `ChromaClient` и один `MCPTool`, а все операции (добавление, запрос, удаление) выполняются через этот клиент.
- Весь код, связанный с векторными операциями, сосредоточен в одном файле, что упрощает поддержку и соответствует условию «один стек».
**Why the main parts satisfy the requirements**
- `VectorStore` now only talks to a ChromaDB collection (`chromadb.Client`) and uses `mcp_tool.get_embedding` for every document and query.
- The MCPtool implements a deterministic fallback embedding, so the bot can run even without an OpenAI key, while still allowing real embeddings when the key is present.
- The bot loads documents once, stores them in the single ChromaDB collection, and queries that same collection no other vector store is involved.
**Ключевые фрагменты кода**
**Key code excerpts**
`package.json`
```json
{
"dependencies": {
"chromadb": "^0.1.0",
"mcp-tool": "^1.0.0"
}
}
*src/vector_store.py* single ChromaDB collection and MCPtool usage
```python
self.client = chromadb.Client(Settings())
self.collection = self.client.get_or_create_collection(name=collection_name)
...
embeddings.append(get_embedding(doc["text"]))
...
embedding = get_embedding(query_text)
results = self.collection.query(query_embeddings=[embedding], n_results=top_k)
```
`src/vectorStore.js`
```js
const { ChromaClient } = require('chromadb');
const { MCPTool } = require('mcp-tool');
class VectorStore {
constructor() {
this.client = new ChromaClient({ path: './chromadb' });
this.collection = null;
this.mcp = new MCPTool(); // единственный MCP‑tool
}
...
}
*src/mcp_tool.py* one embedding generator with OpenAI fallback
```python
def get_embedding(text: str) -> List[float]:
api_key = os.getenv("OPENAI_API_KEY")
if api_key and openai:
...
return response["data"][0]["embedding"]
return _hash_embedding(text)
```
**Ограничения**
- В текущей реализации нет поддержки альтернативных моделей эмбеддингов; все запросы идут через `MCPTool`.
- Если понадобится другой векторный движок, потребуется повторная рефакторинг.
*src/faq_bot.py* uses the unified `VectorStore`
```python
store = VectorStore()
if store.collection.count() == 0:
docs = load_documents(data_dir)
store.add_documents(docs)
...
results = store.query(query, top_k=3)
```
Таким образом, проект теперь полностью соответствует условию задания: один стек (ChromaDB + один MCPtool) и отсутствие других векторных хранилищ.
**Honest limitations**
- The deterministic dummy embedding may reduce retrieval quality when no OpenAI key is set.
- ChromaDB is embedded in memory by default; persistence depends on the local ChromaDB configuration.
- No additional vector store is introduced, but the fallback embedding is a simple hashbased vector, not a true semantic embedding.
This refactor satisfies the assignment: a single stack (ChromaDB + one MCPtool) is used, the FAQ bot remains functional, and no extra vector stores are present.