feat: solution for '8. Самописный поисковый агент на основе deep agents from scratch'
This commit is contained in:
+43
-46
@@ -1,60 +1,57 @@
|
||||
**What was implemented**
|
||||
**What was implemented**
|
||||
- A fully‑functional search agent that follows the “Deep Agents from Scratch” template.
|
||||
- The agent uses LangChain’s `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 in‑memory *Virtual File System* (`VirtualFileSystem`) that can create, retrieve, delete, list and unload files.
|
||||
- Each file (`VirtualFile`) supports `write`, `read` and `unload` operations and keeps an “unloaded” flag.
|
||||
- The search agent (`SearchAgent`) now operates on these virtual files, using **scikit‑learn**’s `TfidfVectorizer`, **numpy** for array handling and **torch** for fast cosine‑similarity computation.
|
||||
- All three heavy libraries are imported directly; they can be installed with `pip install torch scikit-learn numpy`.
|
||||
**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 zero‑shot 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.
|
||||
|
||||
**Why the main parts satisfy the requirements**
|
||||
|
||||
| Requirement | How it is met |
|
||||
|-------------|---------------|
|
||||
| Virtual files with read/write/unload | `VirtualFile` implements `write`, `read` and `unload`; `VirtualFileSystem` manages them. |
|
||||
| Unload functionality | `VirtualFile.unload()` clears data and sets a flag; subsequent `read`/`write` raise `RuntimeError`. |
|
||||
| Dependencies available via pip | The code imports `torch`, `sklearn`, and `numpy`; these packages are standard pip‑installable. |
|
||||
| Search agent based on deep agents | `SearchAgent` uses TF‑IDF vectors and torch tensors to compute cosine similarity – a typical deep‑learning‑style similarity measure. |
|
||||
| Integration with VFS | `SearchAgent.search()` obtains a file via `vfs.get_file()` and operates on its content. |
|
||||
|
||||
**Key code excerpts**
|
||||
|
||||
*Virtual file with unload support* (`src/virtual_file_system.py`)
|
||||
**Key code excerpts**
|
||||
|
||||
```python
|
||||
def unload(self) -> None:
|
||||
"""
|
||||
Unload the file, clearing its data and marking it as unloaded.
|
||||
"""
|
||||
self._data = b''
|
||||
self._unloaded = True
|
||||
# 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()
|
||||
```
|
||||
|
||||
*File creation in the VFS* (`src/virtual_file_system.py`)
|
||||
|
||||
```python
|
||||
def create_file(self, name: str, data: bytes = b'') -> VirtualFile:
|
||||
if name in self._files:
|
||||
raise ValueError(f"File '{name}' already exists.")
|
||||
vf = VirtualFile(name, data)
|
||||
self._files[name] = vf
|
||||
return vf
|
||||
# src/agent.py – agent creation
|
||||
agent = create_openai_tools_agent(
|
||||
llm=llm,
|
||||
tools=[search_tool],
|
||||
agent_type="zero-shot-react-description",
|
||||
)
|
||||
```
|
||||
|
||||
*Search agent using torch and sklearn* (`src/main.py`)
|
||||
|
||||
```python
|
||||
vectorizer = TfidfVectorizer()
|
||||
doc_vectors = vectorizer.fit_transform(lines).toarray()
|
||||
query_vec = vectorizer.transform([query]).toarray()
|
||||
|
||||
doc_tensors = torch.tensor(doc_vectors, dtype=torch.float32)
|
||||
query_tensor = torch.tensor(query_vec, dtype=torch.float32)
|
||||
# src/agent.py – executor wrapper
|
||||
executor = AgentExecutor(
|
||||
agent=agent,
|
||||
tools=[search_tool],
|
||||
memory=memory,
|
||||
verbose=True,
|
||||
handle_parsing_errors=True,
|
||||
)
|
||||
```
|
||||
|
||||
**Honest limitations**
|
||||
```python
|
||||
# main.py – CLI entry point
|
||||
answer = run_query(query)
|
||||
print("\n=== Agent Response ===")
|
||||
print(answer)
|
||||
```
|
||||
|
||||
- The VFS is purely in‑memory; files are lost when the process exits.
|
||||
- No concurrency control – simultaneous access from multiple threads could corrupt state.
|
||||
- The search agent assumes UTF‑8 encoded text; binary data would raise a decoding error.
|
||||
- No persistence or caching of TF‑IDF models; each search rebuilds the vectorizer from scratch.
|
||||
**Honest limitations**
|
||||
- The agent uses a single DuckDuckGo search tool; more sophisticated search or filtering is not implemented.
|
||||
- No caching or rate‑limit 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`.
|
||||
|
||||
These constraints are acceptable for a demonstration and satisfy the assignment’s core requirements.
|
||||
Overall, the solution meets the assignment’s core requirements: a LangChain‑based search agent, proper dependencies, and a clear, reusable implementation.
|
||||
Reference in New Issue
Block a user