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.
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.
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.
## Features
- **Virtual File System** CRUD operations for memory entries.
- **LLM abstraction** Uses OpenAI GPT3.5Turbo if `OPENAI_API_KEY` is set, otherwise falls back to a mock echo.
- **RAG Agent** Retrieves relevant memory, builds a prompt, and generates an answer.
- **RESTful API** Endpoints for managing memory and querying the agent.
- **Unit tests** Jest tests for VFS and Agent logic.
- **Updated Agent Initialization**: Uses `initializeAgentExecutorWithOptions` from LangChain.
- **Custom Text Splitter**: Configured with a chunk size of 1000 characters and an overlap of 200 characters.
- **RAG Memory**: Embeddings are stored in a FAISS vector store and queried via a RetrievalQA chain.
- **Simple Test Harness**: Runs a sample query and prints the agent's response.
## Installation
## Prerequisites
- Node.js v18 or newer
- npm
## Setup
```bash
git clone https://git.brojs.ru/kuzakhmetovartur/prakticheskoe-zadanie-agent-s-rag-pamyat.git
cd prakticheskoe-zadanie-agent-s-rag-pamyat
# Clone the repository
git clone https://github.com/your-username/agent-rag-memory.git
cd agent-rag-memory
# Install dependencies
npm install
# Create a .env file with your OpenAI API key
echo "OPENAI_API_KEY=your_api_key_here" > .env
```
## Environment Variables
Create a `.env` file based on `.env.example`:
## Running the Agent
```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
```
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?"}'
```
## Testing
Run unit tests with coverage:
```bash
npm test
=== Agent Response ===
Paris
```
## Project Structure
```
src/
index.ts # Server entry point
agent.ts # RAG agent logic
llm.ts # LLM abstraction
vfs.ts # Virtual file system
utils.ts # Helpers
routes.ts # Express routes
middleware.ts # Error handling & validation
tests/
vfs.test.ts
agent.test.ts
agent-rag-memory/
├── src/
└── index.ts # Main implementation
├── package.json
├── tsconfig.json
└── README.md
```
## 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",
"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",
"type": "commonjs",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "ts-node src/index.ts",
"test": "jest --coverage"
"start": "ts-node src/index.ts"
},
"keywords": [
"RAG",
"LLM",
"virtual-file-system",
"express",
"langchain",
"rag",
"agent",
"typescript"
],
"author": "Your Name",
"license": "MIT",
"dependencies": {
"dotenv": "^16.4.5",
"express": "^4.18.2",
"uuid": "^9.0.0"
},
"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",
"@types/node": "^20.11.0",
"langchain": "^0.0.202",
"openai": "^4.20.0",
"ts-node": "^10.9.1",
"typescript": "^5.3.3"
}
}
+74 -21
View File
@@ -1,27 +1,80 @@
import express from 'express';
import dotenv from 'dotenv';
import bodyParser from 'body-parser';
import { VirtualFileSystem } from './vfs';
import { LLM } from './llm';
import { Agent } from './agent';
import { createRoutes } from './routes';
import { errorHandler } from './middleware';
import { OpenAI } from "langchain/llms/openai";
import { OpenAIEmbeddings } from "langchain/embeddings/openai";
import { FAISS } from "langchain/vectorstores/faiss";
import { RetrievalQA } from "langchain/chains/retrieval-qa";
import { Tool } from "langchain/tools/base";
import { initializeAgentExecutorWithOptions } from "langchain/agents";
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
import * as dotenv from "dotenv";
dotenv.config();
const app = express();
const port = process.env.PORT ? parseInt(process.env.PORT, 10) : 3000;
async function main() {
// 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();
const llm = new LLM();
const agent = new Agent(vfs, llm);
app.use('/', createRoutes(agent));
app.use(errorHandler);
app.listen(port, () => {
console.log(`RAG Memory Agent listening on port ${port}`);
// Text splitter configuration (chunk size 1000, overlap 200)
const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 1000,
chunkOverlap: 200,
});
// Split the document into chunks
const docs = await splitter.splitText(sampleText);
// Initialize embeddings and vector store
const embeddings = new OpenAIEmbeddings({ openAIApiKey: apiKey });
const vectorStore = await FAISS.fromTexts(docs, [], embeddings);
// Initialize LLM
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": {
"target": "ES2020",
"module": "CommonJS",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true
"outDir": "dist",
"rootDir": "src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "**/*.test.ts"]
"include": ["src"]
}