feat: solution for '8. Самописный поисковый агент на основе deep agents from scratch'
This commit is contained in:
@@ -1,43 +1,68 @@
|
|||||||
# DeepAgent
|
# Deep Search Agent – LangChain Implementation
|
||||||
|
|
||||||
DeepAgent is a minimal example of a deep learning based search agent.
|
This repository contains a minimal implementation of a **search agent** built with LangChain, following the “Deep Agents from Scratch” template.
|
||||||
It demonstrates how to combine a neural network with a simple search algorithm
|
The agent can answer arbitrary questions by performing a web search and reasoning over the results.
|
||||||
(Monte‑Carlo Tree Search style) without relying on external search libraries.
|
|
||||||
|
|
||||||
## Installation
|
## Features
|
||||||
|
|
||||||
|
- Uses **OpenAI GPT‑4o‑mini** as the language model.
|
||||||
|
- Performs web searches via **SerpAPI** (Google/SerpAPI).
|
||||||
|
- Maintains conversation context with a memory buffer.
|
||||||
|
- Implements the **Zero‑Shot React** agent pattern.
|
||||||
|
- Simple command‑line interface for interactive use.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Python 3.10+
|
||||||
|
- An OpenAI API key.
|
||||||
|
- A SerpAPI key (free tier available).
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Create a virtual environment (recommended)
|
# Clone the repository
|
||||||
python -m venv .venv
|
git clone https://git.brojs.ru/kuzakhmetovartur/8.-samopisnyy-poiskovyy-agent-na-osnove-<repo>.git
|
||||||
source .venv/bin/activate # On Windows use `.venv\\Scripts\\activate`
|
cd <repo>
|
||||||
|
|
||||||
# Install the package
|
# Create a virtual environment (optional but recommended)
|
||||||
pip install .
|
python -m venv .venv
|
||||||
|
source .venv/bin/activate # On Windows: .venv\\Scripts\\activate
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a `.env` file in the project root with your credentials:
|
||||||
|
|
||||||
|
```
|
||||||
|
OPENAI_API_KEY=sk-...
|
||||||
|
SERPAPI_KEY=your-serpapi-key
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```python
|
Run the agent interactively:
|
||||||
from src.search_agent import SearchAgent, PolicyValueNet
|
|
||||||
|
|
||||||
# Create a policy‑value network
|
|
||||||
net = PolicyValueNet(input_dim=1, action_space=2)
|
|
||||||
|
|
||||||
# Create the agent
|
|
||||||
agent = SearchAgent(policy_value_net=net, max_depth=3)
|
|
||||||
|
|
||||||
# Run the agent on a simple state
|
|
||||||
state = 0
|
|
||||||
action = agent.act(state)
|
|
||||||
print(f"Chosen action: {action}")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running Tests
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pytest
|
python -m src.agent
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You will be prompted to enter a question. The agent will search the web and return a concise answer.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```
|
||||||
|
Enter your question: What is the capital of France?
|
||||||
|
Processing...
|
||||||
|
|
||||||
|
=== Answer ===
|
||||||
|
The capital of France is Paris.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
The agent can be tested programmatically by importing `create_search_agent` from `src.agent` and calling `agent.run("your question")`.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT License – see the [LICENSE](LICENSE) file for details.
|
MIT License
|
||||||
+5
-3
@@ -1,3 +1,5 @@
|
|||||||
torch==2.1.0
|
langchain==0.2.0
|
||||||
pytest==7.4.0
|
langchain-openai==0.1.0
|
||||||
coverage==7.3.0
|
langchain-community==0.2.0
|
||||||
|
openai==1.12.0
|
||||||
|
python-dotenv==1.0.0
|
||||||
+167
-19
@@ -1,29 +1,177 @@
|
|||||||
"""
|
"""
|
||||||
Base Agent class.
|
Deep Agents from Scratch – Search Agent Implementation
|
||||||
|
======================================================
|
||||||
|
|
||||||
|
This module implements a search agent using LangChain following the
|
||||||
|
“Deep Agents from Scratch” template. The agent can answer arbitrary
|
||||||
|
questions by performing a web search and reasoning over the results.
|
||||||
|
|
||||||
|
Prerequisites
|
||||||
|
-------------
|
||||||
|
* Python 3.10+
|
||||||
|
* The following environment variables must be set:
|
||||||
|
* OPENAI_API_KEY – OpenAI API key
|
||||||
|
* SERPAPI_KEY – SerpAPI key (for web search)
|
||||||
|
* Install dependencies:
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
Run the module directly to start a simple CLI:
|
||||||
|
|
||||||
|
python -m src.agent
|
||||||
|
|
||||||
|
You will be prompted to enter a question. The agent will perform a
|
||||||
|
search and return a concise answer.
|
||||||
|
|
||||||
|
Author
|
||||||
|
------
|
||||||
|
Artur Kuzakhmetov
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from abc import ABC, abstractmethod
|
import os
|
||||||
from typing import Any, List
|
import sys
|
||||||
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from langchain.agents import AgentExecutor, ZeroShotAgent, Tool
|
||||||
|
from langchain.agents.agent import AgentOutputParser
|
||||||
|
from langchain.chat_models import ChatOpenAI
|
||||||
|
from langchain.memory import ConversationBufferMemory
|
||||||
|
from langchain.tools import BaseTool
|
||||||
|
from langchain_community.tools.serpapi import SerpAPIWrapper
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# Load environment variables
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
load_dotenv() # Loads .env file if present
|
||||||
|
|
||||||
|
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
|
||||||
|
SERPAPI_KEY = os.getenv("SERPAPI_KEY")
|
||||||
|
|
||||||
|
if not OPENAI_API_KEY:
|
||||||
|
raise RuntimeError("OPENAI_API_KEY environment variable is not set.")
|
||||||
|
if not SERPAPI_KEY:
|
||||||
|
raise RuntimeError("SERPAPI_KEY environment variable is not set.")
|
||||||
|
|
||||||
|
|
||||||
class Agent(ABC):
|
# --------------------------------------------------------------------------- #
|
||||||
|
# Tool definitions
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
def create_serpapi_tool() -> BaseTool:
|
||||||
"""
|
"""
|
||||||
Abstract base class for agents.
|
Creates a SerpAPI web search tool.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
BaseTool
|
||||||
|
A LangChain tool that performs a web search using SerpAPI.
|
||||||
"""
|
"""
|
||||||
|
serpapi = SerpAPIWrapper(
|
||||||
|
serpapi_api_key=SERPAPI_KEY,
|
||||||
|
# We only need the top 5 results to keep the output concise
|
||||||
|
num_results=5,
|
||||||
|
)
|
||||||
|
return Tool(
|
||||||
|
name="WebSearch",
|
||||||
|
func=serpapi.run,
|
||||||
|
description=(
|
||||||
|
"Use this tool to perform a web search. "
|
||||||
|
"Input should be a concise query. "
|
||||||
|
"Return the top results as a short summary."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def act(self, state: Any) -> Any:
|
|
||||||
"""
|
|
||||||
Choose an action given a state.
|
|
||||||
|
|
||||||
Parameters
|
# --------------------------------------------------------------------------- #
|
||||||
----------
|
# Agent construction
|
||||||
state : Any
|
# --------------------------------------------------------------------------- #
|
||||||
Current state.
|
def create_search_agent() -> AgentExecutor:
|
||||||
|
"""
|
||||||
|
Builds a search agent following the Deep Agents from Scratch template.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
Any
|
AgentExecutor
|
||||||
Selected action.
|
An executable agent that can answer arbitrary questions by
|
||||||
"""
|
searching the web and reasoning over the results.
|
||||||
pass
|
"""
|
||||||
|
# LLM configuration
|
||||||
|
llm = ChatOpenAI(
|
||||||
|
model_name="gpt-4o-mini",
|
||||||
|
temperature=0.2,
|
||||||
|
openai_api_key=OPENAI_API_KEY,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Memory to keep conversation context
|
||||||
|
memory = ConversationBufferMemory(
|
||||||
|
memory_key="chat_history",
|
||||||
|
return_messages=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Tools available to the agent
|
||||||
|
tools = [create_serpapi_tool()]
|
||||||
|
|
||||||
|
# Prompt template for the zero-shot-react agent
|
||||||
|
# The template is derived from LangChain's ZeroShotAgent
|
||||||
|
prompt = ZeroShotAgent.create_prompt(
|
||||||
|
tools=tools,
|
||||||
|
llm=llm,
|
||||||
|
prefix="You are a helpful assistant that can search the web to answer questions.",
|
||||||
|
suffix=(
|
||||||
|
"When you need to search the web, use the following tool:\n"
|
||||||
|
"Tool: {tool_name}\n"
|
||||||
|
"Input: {tool_input}\n"
|
||||||
|
"When you have the answer, respond with the final answer."
|
||||||
|
),
|
||||||
|
input_variables=["input", "intermediate_steps"],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Agent
|
||||||
|
agent = ZeroShotAgent(
|
||||||
|
llm=llm,
|
||||||
|
tools=tools,
|
||||||
|
prompt=prompt,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Agent executor
|
||||||
|
executor = AgentExecutor.from_agent_and_tools(
|
||||||
|
agent=agent,
|
||||||
|
tools=tools,
|
||||||
|
memory=memory,
|
||||||
|
verbose=True,
|
||||||
|
handle_parsing_errors=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
return executor
|
||||||
|
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# CLI entry point
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
def main() -> None:
|
||||||
|
"""
|
||||||
|
Simple command‑line interface that prompts the user for a question
|
||||||
|
and prints the agent's answer.
|
||||||
|
"""
|
||||||
|
agent = create_search_agent()
|
||||||
|
|
||||||
|
print("Deep Search Agent (press Ctrl+C to exit)")
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
query = input("\nEnter your question: ").strip()
|
||||||
|
if not query:
|
||||||
|
continue
|
||||||
|
print("\nProcessing...\n")
|
||||||
|
result = agent.run(query)
|
||||||
|
print("\n=== Answer ===")
|
||||||
|
print(result)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nExiting.")
|
||||||
|
sys.exit(0)
|
||||||
|
except Exception as exc:
|
||||||
|
print(f"\nError: {exc}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user