feat: solution for 'Агент с RAG-памятью'
CI / build (push) Has been cancelled

This commit is contained in:
2026-07-01 13:08:56 +03:00
parent 6da212bf32
commit 6022a43714
7 changed files with 260 additions and 202 deletions
+21
View File
@@ -0,0 +1,21 @@
import { OllamaEmbeddings } from 'ollama-embeddings';
/**
* Singleton instance of OllamaEmbeddings.
* The model name can be overridden via the OLLAMA_MODEL environment variable.
*/
const modelName = process.env.OLLAMA_MODEL || 'all-minilm';
export const embeddings = new OllamaEmbeddings({
model: modelName,
// Optional: specify the Ollama host if not default
host: process.env.OLLAMA_HOST || 'http://localhost:11434'
});
/**
* Utility to embed a single string.
* @param {string} text
* @returns {Promise<number[]>} embedding vector
*/
export async function embedText(text) {
return await embeddings.embedQuery(text);
}
+66 -2
View File
@@ -1,3 +1,67 @@
const Agent = require('./agent');
import dotenv from 'dotenv';
import readline from 'readline';
import { search_knowledge_base } from './tools/searchKnowledgeBase.js';
import { add_to_knowledge_base } from './tools/addToKnowledgeBase.js';
module.exports = { Agent };
dotenv.config();
/**
* Simple command-line agent that supports two commands:
* 1. /search <query> - searches the knowledge base
* 2. /add <content> - adds content to the knowledge base
* Any other input is treated as a normal message and the agent echoes it back.
*/
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: 'Agent> '
});
console.log('Agent with RAG memory using Ollama embeddings.');
console.log('Commands:');
console.log(' /search <query> - Search knowledge base');
console.log(' /add <content> - Add content to knowledge base');
console.log(' /exit - Exit');
rl.prompt();
rl.on('line', async (line) => {
const trimmed = line.trim();
if (trimmed === '/exit') {
rl.close();
return;
}
if (trimmed.startsWith('/search ')) {
const query = trimmed.slice(8).trim();
if (!query) {
console.log('Please provide a query.');
} else {
console.log(`Searching for "${query}"...`);
const results = await search_knowledge_base(query);
if (results.length === 0) {
console.log('No relevant documents found.');
} else {
console.log('Top results:');
results.forEach((res, idx) => {
console.log(`${idx + 1}. [${res.id}] (${res.score.toFixed(4)})`);
console.log(` ${res.content}`);
});
}
}
} else if (trimmed.startsWith('/add ')) {
const content = trimmed.slice(5).trim();
if (!content) {
console.log('Please provide content to add.');
} else {
const { id } = await add_to_knowledge_base(content);
console.log(`Content added with id ${id}.`);
}
} else {
// Echo back the message (placeholder for more complex agent logic)
console.log(`You said: ${trimmed}`);
}
rl.prompt();
}).on('close', () => {
console.log('Goodbye!');
process.exit(0);
});
+15
View File
@@ -0,0 +1,15 @@
import { embeddings } from '../embeddings.js';
import { knowledgeBase } from './searchKnowledgeBase.js';
import { v4 as uuidv4 } from 'uuid';
/**
* Add new content to the knowledge base.
* @param {string} content
* @returns {Promise<{id: string}>}
*/
export async function add_to_knowledge_base(content) {
const embedding = await embeddings.embedQuery(content);
const id = uuidv4();
knowledgeBase.push({ id, content, embedding });
return { id };
}
+42
View File
@@ -0,0 +1,42 @@
import { embeddings } from '../embeddings.js';
/**
* In-memory knowledge base.
* Each entry: { id, content, embedding }
*/
const knowledgeBase = [];
/**
* Compute cosine similarity between two vectors.
* @param {number[]} a
* @param {number[]} b
* @returns {number}
*/
function cosineSimilarity(a, b) {
const dot = a.reduce((sum, ai, i) => sum + ai * b[i], 0);
const normA = Math.sqrt(a.reduce((sum, ai) => sum + ai * ai, 0));
const normB = Math.sqrt(b.reduce((sum, bi) => sum + bi * bi, 0));
return dot / (normA * normB);
}
/**
* Search the knowledge base for the most relevant documents.
* @param {string} query
* @param {number} topK
* @returns {Promise<Array<{id: string, content: string, score: number}>>}
*/
export async function search_knowledge_base(query, topK = 3) {
const queryEmbedding = await embeddings.embedQuery(query);
const scored = knowledgeBase.map(entry => ({
id: entry.id,
content: entry.content,
score: cosineSimilarity(queryEmbedding, entry.embedding)
}));
scored.sort((a, b) => b.score - a.score);
return scored.slice(0, topK);
}
/**
* Expose the knowledge base for other modules (e.g., add tool).
*/
export { knowledgeBase };