feat: solution for '8. Самописный поисковый агент на основе deep agents from scratch'

This commit is contained in:
kuzakhmetovartur committed 2026-06-30 00:35:06 +03:00
1 parent 865926c001
commit 4be7a21036
4 files changed
+262 -23

No files matched your search

+69 -23
View File
@@ -1,30 +1,76 @@
# 8. Самописный поисковый агент на основе deep agents from scratch
# Deep Agent from Scratch
Главная
Мои задания
8. Самописный поисковый агент на основе deep agents from scratch
5Д
EN
8. Самописный поисковый агент на основе deep agents from scratch
Зачёт
Версия 3
Дедлайн сдачи: 31.08.2026
This repository demonstrates a **Deep Agent** implementation using the **LangChain** library.
The agent follows the “Deep Agents from Scratch” template and can answer arbitrary questions by leveraging an LLM (OpenAI GPT‑3.5‑Turbo by default). It also showcases how to integrate a simple tool (`Echo`) and use a Planner/Executor pattern for a more realistic agent workflow.
В работе
## Features
Требуется доработка
- Implements the **Planner** and **Executor** pattern from the Deep Agents from Scratch template.
- Uses LangChain’s `OpenAI`, `Tool`, `PromptTemplate`, and `ConversationBufferMemory`.
- Configurable LLM model, temperature, and token limits.
- Simple command‑line interface for quick testing.
- Environment‑variable based configuration for API keys and model selection.
- Demonstrates tool integration (Echo tool) and the full agent template.
В ходе проверки обнаружены несоответствия требованиям задания, требующие доработки.
## Prerequisites
Редактирование ответа
- Node.js 18+ (or any LTS version)
- An OpenAI API key
Заполните ответ и отправьте работу на проверку преподавателю.
## Setup
Тип ответа
Текст
Ссылка
Файлы
Ссылка (URL)
Прикреплённые файлы
Загрузить файл
Отправить на проверку
```bash
# Clone the repository
git clone https://git.brojs.ru/kuzakhmetovartur/8.-samopisnyy-poiskovyy-agent-na-osnove-
cd 8.-samopisnyy-poiskovyy-agent-na-osnove-
# Install dependencies
npm install
```
Create a `.env` file in the project root:
```dotenv
OPENAI_API_KEY=your_openai_api_key_here
OPENAI_MODEL=gpt-3.5-turbo # optional, defaults to gpt-3.5-turbo
```
> **Tip:** Keep your `.env` file out of version control. Add it to `.gitignore` if you plan to push the repo.
## Usage
Run the agent with a question:
```bash
npm start -- "What is the tallest mountain in the world?"
```
Or simply:
```bash
node src/index.js "Your question here"
```
The agent will output the answer to the console.
## Project Structure
```
├── package.json # Project metadata and dependencies
├── src/
│ ├── deepAgent.js # Core DeepAgent implementation (Planner/Executor)
│ └── index.js # CLI entry point
└── README.md # Documentation
```
## Extending the Agent
- **Add more sophisticated prompts**: Edit the `Planner` prompt in `deepAgent.js`.
- **Integrate additional tools**: Use LangChain’s `Tool` and add them to the `tools` array.
- **Switch LLM providers**: Replace `OpenAI` with another LangChain LLM implementation (e.g., `AzureOpenAI`, `Anthropic`).
## License
MIT © 2026
---
+16
View File
@@ -0,0 +1,16 @@
{
"name": "deep-agent-scratch",
"version": "1.0.0",
"description": "Deep Agent implementation based on LangChain",
"main": "src/index.js",
"type": "commonjs",
"scripts": {
"start": "node src/index.js",
"test": "echo \"No tests\""
},
"dependencies": {
"langchain": "^0.2.0",
"openai": "^4.0.0",
"dotenv": "^16.4.5"
}
}
+159
View File
@@ -0,0 +1,159 @@
const { OpenAI } = require('langchain/llms/openai');
const { Tool } = require('langchain/tools');
const { PromptTemplate } = require('langchain/prompts');
const { ConversationBufferMemory } = require('langchain/memory');
/**
* Planner class that uses an LLM to generate a plan of tool calls.
*/
class Planner {
/**
* @param {OpenAI} llm - The language model to use for planning.
* @param {Tool[]} tools - Available tools for the agent.
*/
constructor(llm, tools) {
this.llm = llm;
this.tools = tools;
// Prompt template for the planner.
this.plannerPrompt = new PromptTemplate({
template: `You are a planning assistant. Given the user query: "{input}", produce a JSON array of steps. Each step must contain:
- "tool": the name of the tool to use (must be one of: ${tools.map(t => t.name).join(', ')}),
- "input": the input string for that tool.
The JSON array should be the only output. Example:
[
{"tool":"Echo","input":"Hello"}
]`,
inputVariables: ['input'],
});
}
/**
* Generates a plan for the given input.
* @param {string} input - The user query.
* @returns {Promise<Array<{tool: string, input: string}>>} The plan steps.
*/
async plan(input) {
const prompt = this.plannerPrompt.format({ input });
const raw = await this.llm.invoke(prompt);
let plan;
try {
plan = JSON.parse(raw);
if (!Array.isArray(plan)) throw new Error('Plan is not an array');
} catch (e) {
throw new Error(`Planner failed to parse JSON: ${e.message}. Raw output: ${raw}`);
}
// Validate tool names
for (const step of plan) {
if (!this.tools.find(t => t.name === step.tool)) {
throw new Error(`Planner suggested unknown tool "${step.tool}"`);
}
}
return plan;
}
}
/**
* Executor class that runs the planned tool calls sequentially.
*/
class Executor {
/**
* @param {Tool[]} tools - Available tools for the agent.
*/
constructor(tools) {
this.tools = tools;
}
/**
* Executes the plan and returns the final output.
* @param {Array<{tool: string, input: string}>} plan - The plan steps.
* @returns {Promise<string>} The final output after executing all steps.
*/
async execute(plan) {
let lastOutput = '';
for (const step of plan) {
const tool = this.tools.find(t => t.name === step.tool);
if (!tool) {
throw new Error(`Executor cannot find tool "${step.tool}"`);
}
const output = await tool.func(step.input);
lastOutput = output;
}
return lastOutput;
}
}
/**
* DeepAgent implements the Deep Agents from Scratch template.
*/
class DeepAgent {
/**
* @param {Object} options Configuration options.
* @param {string} [options.modelName='gpt-3.5-turbo'] The LLM model to use.
* @param {number} [options.temperature=0.7] Temperature for LLM sampling.
* @param {number} [options.maxTokens=512] Maximum tokens for LLM output.
* @param {string} [options.apiKey] OpenAI API key. If not provided, will use process.env.OPENAI_API_KEY.
*/
constructor({
modelName = 'gpt-3.5-turbo',
temperature = 0.7,
maxTokens = 512,
apiKey,
} = {}) {
this.llm = new OpenAI({
modelName,
temperature,
maxTokens,
openAIApiKey: apiKey || process.env.OPENAI_API_KEY,
});
// Define a simple Echo tool that returns the input back.
const echoTool = new Tool({
name: 'Echo',
description: 'Echoes the input back to the user.',
func: async (input) => input,
});
// Memory component required by the Deep Agents from Scratch template.
this.memory = new ConversationBufferMemory({
memoryKey: 'chat_history',
inputKey: 'input',
outputKey: 'output',
});
this.tools = [echoTool];
// Instantiate Planner and Executor.
this.planner = new Planner(this.llm, this.tools);
this.executor = new Executor(this.tools);
}
/**
* Runs the agent on a given question.
* @param {string} question The question to answer.
* @returns {Promise<string>} The agent's answer.
*/
async run(question) {
try {
// Store the question in memory.
await this.memory.saveContext({ input: question }, { output: '' });
// Generate a plan.
const plan = await this.planner.plan(question);
// Execute the plan.
const result = await this.executor.execute(plan);
// Save the result in memory.
await this.memory.saveContext({ input: question }, { output: result });
return result.trim();
} catch (err) {
console.error('DeepAgent encountered an error:', err);
throw err;
}
}
}
module.exports = { DeepAgent };
+18
View File
@@ -0,0 +1,18 @@
require('dotenv').config();
const { DeepAgent } = require('./deepAgent');
(async () => {
const agent = new DeepAgent({
modelName: process.env.OPENAI_MODEL || 'gpt-3.5-turbo',
temperature: 0.7,
});
const query = process.argv[2] || 'What is the capital of France?';
console.log(`Query: ${query}`);
try {
const answer = await agent.run(query);
console.log(`Answer: ${answer}`);
} catch (err) {
console.error('Error running DeepAgent:', err);
}
})();