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

This commit is contained in:
2026-07-01 15:10:08 +03:00
parent f522dcfa80
commit 51ab1df383
6 changed files with 161 additions and 239 deletions
+26 -67
View File
@@ -1,70 +1,29 @@
require('dotenv').config();
const express = require('express');
const { OpenAI } = require('openai');
const { ChromaClient } = require('chromadb');
const { moderateInput } = require('./middleware');
const Bot = require('./bot');
const app = express();
app.use(express.json());
const faqs = [
{
id: '1',
question: 'What is ChromaDB?',
answer: 'ChromaDB is a vector database designed for storing and querying embeddings efficiently.',
},
{
id: '2',
question: 'How do I use MCP-tool?',
answer: 'MCP-tool is a utility that generates embeddings from text using a chosen model.',
},
{
id: '3',
question: 'Can I delete a document from the vector store?',
answer: 'Yes, you can delete a document by its ID using the deleteDocument method.',
},
];
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const chroma = new ChromaClient({ path: 'chromadb' });
(async () => {
const bot = new Bot();
await bot.init();
await bot.indexFAQs(faqs);
const COLLECTION_NAME = 'faq_collection';
const TOP_K = 3;
// Initialize collection
let collectionPromise = chroma.getOrCreateCollection({
name: COLLECTION_NAME,
metadata: { description: 'FAQ embeddings' }
});
app.post('/ask', async (req, res) => {
try {
const { question } = req.body;
if (!question) {
return res.status(400).json({ error: 'Question is required' });
}
// Moderate user input
const moderationResult = await moderateInput(question);
if (!moderationResult.allowed) {
return res.status(403).json({
error: 'Question contains disallowed content',
reasons: moderationResult.reasons
});
}
// Embed the question
const embeddingResponse = await openai.embeddings.create({
model: 'text-embedding-ada-002',
input: question
});
const embedding = embeddingResponse.data[0].embedding;
// Query ChromaDB
const collection = await collectionPromise;
const queryResult = await collection.query({
queryEmbeddings: [embedding],
nResults: TOP_K,
includeMetadata: true
});
if (!queryResult.ids || queryResult.ids.length === 0) {
return res.json({ answer: "I don't have an answer for that." });
}
// Pick the top result
const topAnswer = queryResult.metadatas[0]?.answer || "I don't have an answer for that.";
res.json({ answer: topAnswer });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Internal server error' });
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`FAQ bot listening on port ${PORT}`);
});
const userQuestion = 'Explain ChromaDB';
const response = await bot.answer(userQuestion);
console.log('Answer:\n', response);
})();