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.
|
||||
It demonstrates how to combine a neural network with a simple search algorithm
|
||||
(Monte‑Carlo Tree Search style) without relying on external search libraries.
|
||||
This repository contains a minimal implementation of a **search agent** built with LangChain, following the “Deep Agents from Scratch” template.
|
||||
The agent can answer arbitrary questions by performing a web search and reasoning over the results.
|
||||
|
||||
## 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
|
||||
# Create a virtual environment (recommended)
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate # On Windows use `.venv\\Scripts\\activate`
|
||||
# Clone the repository
|
||||
git clone https://git.brojs.ru/kuzakhmetovartur/8.-samopisnyy-poiskovyy-agent-na-osnove-<repo>.git
|
||||
cd <repo>
|
||||
|
||||
# Install the package
|
||||
pip install .
|
||||
# Create a virtual environment (optional but recommended)
|
||||
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
|
||||
|
||||
```python
|
||||
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
|
||||
Run the agent interactively:
|
||||
|
||||
```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
|
||||
|
||||
MIT License – see the [LICENSE](LICENSE) file for details.
|
||||
MIT License
|
||||
+5
-3
@@ -1,3 +1,5 @@
|
||||
torch==2.1.0
|
||||
pytest==7.4.0
|
||||
coverage==7.3.0
|
||||
langchain==0.2.0
|
||||
langchain-openai==0.1.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
|
||||
from typing import Any, List
|
||||
import os
|
||||
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
|
||||
----------
|
||||
state : Any
|
||||
Current state.
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Agent construction
|
||||
# --------------------------------------------------------------------------- #
|
||||
def create_search_agent() -> AgentExecutor:
|
||||
"""
|
||||
Builds a search agent following the Deep Agents from Scratch template.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Any
|
||||
Selected action.
|
||||
"""
|
||||
pass
|
||||
Returns
|
||||
-------
|
||||
AgentExecutor
|
||||
An executable agent that can answer arbitrary questions by
|
||||
searching the web and reasoning over the results.
|
||||
"""
|
||||
# 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