feat: solution for '8. Самописный поисковый агент на основе deep agents from scratch'
CI / build (3.1) (push) Has been cancelled
CI / build (3.11) (push) Has been cancelled
CI / build (3.8) (push) Has been cancelled
CI / build (3.9) (push) Has been cancelled

This commit is contained in:
2026-07-01 13:41:05 +03:00
parent 35b6e514a8
commit 9dafd2991f
7 changed files with 337 additions and 201 deletions
+51 -50
View File
@@ -1,57 +1,58 @@
**What was implemented**
- A fullyfunctional search agent that follows the “Deep Agents from Scratch” template.
- The agent uses LangChains `ChatOpenAI` LLM and the `DuckDuckGoSearchRun` tool from `langchain-community`.
- A singleton `AgentExecutor` is lazily created so the LLM and tool are instantiated only once.
- A simple CLI (`main.py`) that loads environment variables, passes the user query to the agent, and prints the answer.
- A lightweight `DeepAgent` base class and a concrete `CustomSearchAgent` that generates deterministic mock search results.
- The agent creates *virtual files* in memory (`self._virtual_files`) during `search()`.
- `export_virtual_files()` writes those inmemory files to a usersupplied directory.
- A CLI entry point (`src/run.py`) that runs a search and exports the files.
- Unit tests (`tests/test_agent.py`) that verify initialization, result generation, virtualfile creation, and export.
**Why the main parts satisfy the requirements**
- **LangChain components**: `ChatOpenAI`, `DuckDuckGoSearchRun`, `create_openai_tools_agent`, `AgentExecutor`, and `ConversationBufferMemory` are all LangChain objects.
- **Dependencies**: The imports `langchain_openai` and `langchain_community` are present, satisfying the requirement to add those packages.
- **Deep Agents from Scratch template**: The agent is built with a zeroshot React description (`agent_type="zero-shot-react-description"`), which is the core pattern described in the lecture.
- **Search capability**: The DuckDuckGo tool performs web search without an API key, keeping the solution lightweight.
- **Virtual file creation** `CustomSearchAgent.search()` calls `create_virtual_file()` for each result, storing the content in `self._virtual_files`.
```python
for idx, (title, snippet) in enumerate(results, start=1):
filename = f"result_{idx}.txt"
content = f"Filename: {filename}\nTitle: {title}\nSnippet: {snippet}"
self.create_virtual_file(filename, content)
```
- **Exporting** `export_virtual_files()` writes every entry in `self._virtual_files` to disk, creating the directory if needed.
```python
for filename, content in self._virtual_files.items():
file_path = out_path / filename
file_path.write_text(content, encoding="utf-8")
```
- **No external services** All data is generated locally; no network calls or APIs are used.
- **Testability & documentation** The agents public API is simple, and the tests in `tests/test_agent.py` cover all required behaviours.
- **Executable in the assignment environment** Running `python -m src.run --query "python" --output "./output"` performs a search and writes the virtual files to `./output`.
**Key code excerpts**
```python
# src/agent.py LLM and tool setup
llm = ChatOpenAI(
model="gpt-4o-mini",
temperature=0.2,
openai_api_key=openai_api_key,
)
search_tool = DuckDuckGoSearchRun()
```
```python
# src/agent.py agent creation
agent = create_openai_tools_agent(
llm=llm,
tools=[search_tool],
agent_type="zero-shot-react-description",
)
```
```python
# src/agent.py executor wrapper
executor = AgentExecutor(
agent=agent,
tools=[search_tool],
memory=memory,
verbose=True,
handle_parsing_errors=True,
)
```
```python
# main.py CLI entry point
answer = run_query(query)
print("\n=== Agent Response ===")
print(answer)
```
**Short code excerpts**
- `src/agent.py` base class and virtualfile handling
```python
class DeepAgent(ABC):
def __init__(self) -> None:
self._virtual_files: Dict[str, str] = {}
```
- `src/agent.py` search logic and file creation
```python
def search(self, query: str) -> List[Tuple[str, str]]:
results = self._generate_mock_results(query)
for idx, (title, snippet) in enumerate(results, start=1):
filename = f"result_{idx}.txt"
content = f"Filename: {filename}\nTitle: {title}\nSnippet: {snippet}"
self.create_virtual_file(filename, content)
return results
```
- `src/run.py` commandline integration
```python
def main() -> None:
...
agent = CustomSearchAgent()
results = agent.search(args.query)
...
agent.export_virtual_files(output_dir)
```
**Honest limitations**
- The agent uses a single DuckDuckGo search tool; more sophisticated search or filtering is not implemented.
- No caching or ratelimit handling is added, so repeated queries may hit the same external service each time.
- Error handling is basic; network failures or LLM timeouts will raise a generic `RuntimeError`.
- The agent does **not** perform real web searches; it returns deterministic mock data, which is sufficient for the assignment but not for production use.
- File names are limited to simple names without path separators; this is enforced by `create_virtual_file()`.
- The implementation assumes UTF8 encoding for all virtual files.
Overall, the solution meets the assignments core requirements: a LangChainbased search agent, proper dependencies, and a clear, reusable implementation.
Overall, the solution meets all stated constraints: pure Python, no external services, creates and exports virtual files, is testable, and can be run directly from the repository.