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

This commit is contained in:
2026-06-25 12:41:22 +03:00
parent 14ab96d098
commit a8a8111eca
4 changed files with 117 additions and 112 deletions
+31 -67
View File
@@ -1,93 +1,57 @@
# RAG Memory Agent # Agent with RAG Memory
A simple Retrieval-Augmented Generation (RAG) memory system built with Node.js, TypeScript, and Express. This project demonstrates a simple LangChain agent that uses Retrieval-Augmented Generation (RAG) to answer questions based on a small set of documents. The implementation is written in TypeScript and follows the latest LangChain initialization patterns.
It stores user data in an inmemory virtual file system and uses a language model (OpenAI or a mock) to answer queries based on stored memory.
## Features ## Features
- **Virtual File System** CRUD operations for memory entries. - **Updated Agent Initialization**: Uses `initializeAgentExecutorWithOptions` from LangChain.
- **LLM abstraction** Uses OpenAI GPT3.5Turbo if `OPENAI_API_KEY` is set, otherwise falls back to a mock echo. - **Custom Text Splitter**: Configured with a chunk size of 1000 characters and an overlap of 200 characters.
- **RAG Agent** Retrieves relevant memory, builds a prompt, and generates an answer. - **RAG Memory**: Embeddings are stored in a FAISS vector store and queried via a RetrievalQA chain.
- **RESTful API** Endpoints for managing memory and querying the agent. - **Simple Test Harness**: Runs a sample query and prints the agent's response.
- **Unit tests** Jest tests for VFS and Agent logic.
## Installation ## Prerequisites
- Node.js v18 or newer
- npm
## Setup
```bash ```bash
git clone https://git.brojs.ru/kuzakhmetovartur/prakticheskoe-zadanie-agent-s-rag-pamyat.git # Clone the repository
cd prakticheskoe-zadanie-agent-s-rag-pamyat git clone https://github.com/your-username/agent-rag-memory.git
cd agent-rag-memory
# Install dependencies
npm install npm install
# Create a .env file with your OpenAI API key
echo "OPENAI_API_KEY=your_api_key_here" > .env
``` ```
## Environment Variables ## Running the Agent
Create a `.env` file based on `.env.example`:
```bash ```bash
cp .env.example .env
```
- `OPENAI_API_KEY` (optional) Your OpenAI API key. If omitted, the agent will use a mock LLM.
- `PORT` Port number for the server (default: 3000).
## Running the Server
```bash
npm run dev # Development with ts-node
# or
npm run build
npm start npm start
``` ```
The server will start on `http://localhost:<PORT>`. You should see output similar to:
## API Endpoints
| Method | Path | Description | Body (JSON) |
|--------|-----------|---------------------------------------------|---------------------------------|
| GET | `/memory` | List all memory entries (id, snippet). | |
| POST | `/memory` | Create a new memory entry. | `{ "content": "string" }` |
| DELETE | `/memory/:id` | Delete a memory entry by ID. | |
| POST | `/query` | Query the agent. | `{ "query": "string" }` |
### Example Requests
```bash
# Add memory
curl -X POST http://localhost:3000/memory \
-H "Content-Type: application/json" \
-d '{"content":"I love programming in TypeScript."}'
# Query
curl -X POST http://localhost:3000/query \
-H "Content-Type: application/json" \
-d '{"query":"What do I like?"}'
``` ```
=== Agent Response ===
## Testing Paris
Run unit tests with coverage:
```bash
npm test
``` ```
## Project Structure ## Project Structure
``` ```
src/ agent-rag-memory/
index.ts # Server entry point ├── src/
agent.ts # RAG agent logic └── index.ts # Main implementation
llm.ts # LLM abstraction ├── package.json
vfs.ts # Virtual file system ├── tsconfig.json
utils.ts # Helpers └── README.md
routes.ts # Express routes
middleware.ts # Error handling & validation
tests/
vfs.test.ts
agent.test.ts
``` ```
## License ## License
MIT © Your Name MIT License
+11 -22
View File
@@ -1,37 +1,26 @@
{ {
"name": "rag-memory-agent", "name": "agent-rag-memory",
"version": "1.0.0", "version": "1.0.0",
"description": "Retrieval-Augmented Generation (RAG) memory system with virtual file system and RESTful API", "description": "A simple LangChain agent with RAG memory implemented in TypeScript",
"main": "dist/index.js", "main": "dist/index.js",
"type": "commonjs",
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
"start": "node dist/index.js", "start": "ts-node src/index.ts"
"dev": "ts-node src/index.ts",
"test": "jest --coverage"
}, },
"keywords": [ "keywords": [
"RAG", "langchain",
"LLM", "rag",
"virtual-file-system", "agent",
"express",
"typescript" "typescript"
], ],
"author": "Your Name", "author": "Your Name",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"dotenv": "^16.4.5", "@types/node": "^20.11.0",
"express": "^4.18.2", "langchain": "^0.0.202",
"uuid": "^9.0.0" "openai": "^4.20.0",
}, "ts-node": "^10.9.1",
"devDependencies": {
"@types/express": "^4.17.21",
"@types/jest": "^29.5.12",
"@types/node": "^20.11.5",
"@types/supertest": "^2.0.12",
"jest": "^29.7.0",
"supertest": "^6.3.3",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.2",
"typescript": "^5.3.3" "typescript": "^5.3.3"
} }
} }
+71 -18
View File
@@ -1,27 +1,80 @@
import express from 'express'; import { OpenAI } from "langchain/llms/openai";
import dotenv from 'dotenv'; import { OpenAIEmbeddings } from "langchain/embeddings/openai";
import bodyParser from 'body-parser'; import { FAISS } from "langchain/vectorstores/faiss";
import { VirtualFileSystem } from './vfs'; import { RetrievalQA } from "langchain/chains/retrieval-qa";
import { LLM } from './llm'; import { Tool } from "langchain/tools/base";
import { Agent } from './agent'; import { initializeAgentExecutorWithOptions } from "langchain/agents";
import { createRoutes } from './routes'; import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
import { errorHandler } from './middleware'; import * as dotenv from "dotenv";
dotenv.config(); dotenv.config();
const app = express(); async function main() {
const port = process.env.PORT ? parseInt(process.env.PORT, 10) : 3000; // Ensure API key is set
const apiKey = process.env.OPENAI_API_KEY;
if (!apiKey) {
console.error("Error: OPENAI_API_KEY environment variable is not set.");
process.exit(1);
}
app.use(bodyParser.json()); // Sample document
const sampleText = `
The quick brown fox jumps over the lazy dog. This sentence is often used to test typing and fonts.
The capital of France is Paris. Paris is known for its art, gastronomy, and culture.
The Earth revolves around the Sun every 365.25 days. The Moon orbits the Earth approximately every 27.3 days.
`;
const vfs = new VirtualFileSystem(); // Text splitter configuration (chunk size 1000, overlap 200)
const llm = new LLM(); const splitter = new RecursiveCharacterTextSplitter({
const agent = new Agent(vfs, llm); chunkSize: 1000,
chunkOverlap: 200,
});
app.use('/', createRoutes(agent)); // Split the document into chunks
const docs = await splitter.splitText(sampleText);
app.use(errorHandler); // Initialize embeddings and vector store
const embeddings = new OpenAIEmbeddings({ openAIApiKey: apiKey });
const vectorStore = await FAISS.fromTexts(docs, [], embeddings);
app.listen(port, () => { // Initialize LLM
console.log(`RAG Memory Agent listening on port ${port}`); const llm = new OpenAI({
openAIApiKey: apiKey,
temperature: 0,
});
// Create RetrievalQA chain
const qaChain = RetrievalQA.fromLLM(llm, vectorStore);
// Define a tool that uses the QA chain
const ragTool = new Tool({
name: "RAG",
description: "Answer questions based on the provided documents using Retrieval-Augmented Generation.",
func: async (input: string) => {
const result = await qaChain.invoke({ query: input });
return result.output as string;
},
});
// Initialize the agent with the updated method
const agent = await initializeAgentExecutorWithOptions(
[ragTool],
llm,
{
agentType: "zero-shot-react-description",
verbose: true,
}
);
// Run a sample query
const query = "What is the capital of France?";
const response = await agent.invoke({ input: query });
console.log("\n=== Agent Response ===");
console.log(response.output);
}
main().catch((err) => {
console.error("Error in main execution:", err);
process.exit(1);
}); });
+4 -5
View File
@@ -2,13 +2,12 @@
"compilerOptions": { "compilerOptions": {
"target": "ES2020", "target": "ES2020",
"module": "CommonJS", "module": "CommonJS",
"outDir": "dist",
"rootDir": "src",
"strict": true, "strict": true,
"esModuleInterop": true, "esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"skipLibCheck": true "outDir": "dist",
"rootDir": "src"
}, },
"include": ["src/**/*"], "include": ["src"]
"exclude": ["node_modules", "**/*.test.ts"]
} }