Update agent.py
This commit is contained in:
@@ -1,121 +1,51 @@
|
|||||||
"""Deep Agent implementation based on LangGraph and LangChain.
|
"""
|
||||||
|
Agent creation using LangChain 1.x `create_agent` API.
|
||||||
|
|
||||||
The module exposes two public functions:
|
This module exposes a single helper `create_agent_executor` that builds an
|
||||||
|
AgentExecutor configured with the custom tools defined in :mod:`tools`.
|
||||||
* ``create_agent`` – returns a :class:`langgraph.graph.StateGraph` that can be
|
|
||||||
executed.
|
|
||||||
* ``create_agent_executor`` – returns an :class:`langchain.agents.AgentExecutor`
|
|
||||||
that can be used directly.
|
|
||||||
|
|
||||||
Both functions lazily import the heavy LangChain/LangGraph dependencies so
|
|
||||||
that the module can be imported even if those packages are not installed.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from langchain_ollama import ChatOllama
|
||||||
|
from langchain.agents import create_agent, AgentExecutor
|
||||||
|
from langchain.tools import BaseTool
|
||||||
|
from typing import List
|
||||||
|
|
||||||
from typing import Any
|
from .tools import search, write_file
|
||||||
|
|
||||||
# Lightweight imports – can be imported eagerly
|
# Define the list of tools that the agent can use
|
||||||
from virtual_fs import VirtualFileSystem
|
TOOLS: List[BaseTool] = [search, write_file]
|
||||||
from tools import WebSearch, CreateVirtualFile, ExportVirtualFiles
|
|
||||||
|
|
||||||
# Shared virtual file system instance used by all tools
|
# LLM configuration – Ollama local model
|
||||||
vfs = VirtualFileSystem()
|
LLM = ChatOllama(model="llama3.1:latest", temperature=0.0)
|
||||||
|
|
||||||
# Define the tools
|
# Create the agent executor using the new LangChain 1.x API
|
||||||
web_search_tool = WebSearch()
|
# The `create_agent` function returns an AgentExecutor instance
|
||||||
create_file_tool = CreateVirtualFile(vfs)
|
# that can be called like a normal function.
|
||||||
export_files_tool = ExportVirtualFiles(vfs)
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
def create_agent_executor() -> AgentExecutor:
|
||||||
# Public API
|
"""Instantiate and return an AgentExecutor.
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def create_agent() -> Any:
|
The executor is configured with:
|
||||||
"""Return a LangGraph graph.
|
* The Ollama Chat model.
|
||||||
|
* The custom tools defined in :mod:`tools`.
|
||||||
The function performs a lazy import of :mod:`langgraph` and related
|
* The default agent type "openai-retrieval-qa" is not used – we rely on
|
||||||
dependencies. If the imports fail, a clear ``ImportError`` is raised.
|
the automatically selected agent type by `create_agent`.
|
||||||
"""
|
"""
|
||||||
try:
|
agent = create_agent(
|
||||||
from langgraph.graph import StateGraph
|
llm=LLM,
|
||||||
from langgraph.prebuilt import create_react_agent as create_agent
|
tools=TOOLS,
|
||||||
from langchain_ollama import ChatOllama
|
|
||||||
from langchain_core.prompts import ChatPromptTemplate
|
|
||||||
from langchain_core.output_parsers import StrOutputParser
|
|
||||||
except Exception as exc: # pragma: no cover
|
|
||||||
raise ImportError(
|
|
||||||
"Failed to import LangGraph/LangChain dependencies. Ensure that the\n"
|
|
||||||
"required packages are installed and the environment is correctly\n"
|
|
||||||
"configured."
|
|
||||||
) from exc
|
|
||||||
|
|
||||||
# LLM and prompt
|
|
||||||
llm = ChatOllama(model="llama3.1")
|
|
||||||
prompt = ChatPromptTemplate.from_messages(
|
|
||||||
[
|
|
||||||
("system", "You are a helpful assistant that can search the web, create virtual files, and export them to disk."),
|
|
||||||
("human", "{input}"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
parser = StrOutputParser()
|
|
||||||
|
|
||||||
# Build a simple agent using LangGraph prebuilt
|
|
||||||
react_agent = create_agent(
|
|
||||||
llm=llm,
|
|
||||||
tools=[web_search_tool, create_file_tool, export_files_tool],
|
|
||||||
prompt=prompt,
|
|
||||||
output_parser=parser,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Create the graph
|
|
||||||
graph = StateGraph()
|
|
||||||
graph.add_node("react_agent", react_agent)
|
|
||||||
graph.set_entry_point("react_agent")
|
|
||||||
graph.set_finish_point("react_agent")
|
|
||||||
return graph
|
|
||||||
|
|
||||||
|
|
||||||
def create_agent_executor() -> Any:
|
|
||||||
"""Return an :class:`langchain.agents.AgentExecutor`.
|
|
||||||
|
|
||||||
The function lazily imports the required classes. It is useful for
|
|
||||||
quick experimentation and for environments where the full graph is
|
|
||||||
unnecessary.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
from langchain.agents import AgentExecutor
|
|
||||||
from langgraph.prebuilt import create_react_agent as create_agent
|
|
||||||
from langchain_ollama import ChatOllama
|
|
||||||
from langchain_core.prompts import ChatPromptTemplate
|
|
||||||
from langchain_core.output_parsers import StrOutputParser
|
|
||||||
except Exception as exc: # pragma: no cover
|
|
||||||
raise ImportError(
|
|
||||||
"Failed to import LangChain dependencies for the AgentExecutor."
|
|
||||||
) from exc
|
|
||||||
|
|
||||||
llm = ChatOllama(model="llama3.1")
|
|
||||||
prompt = ChatPromptTemplate.from_messages(
|
|
||||||
[
|
|
||||||
("system", "You are a helpful assistant that can search the web, create virtual files, and export them to disk."),
|
|
||||||
("human", "{input}"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
parser = StrOutputParser()
|
|
||||||
|
|
||||||
# Build the agent
|
|
||||||
react_agent = create_agent(
|
|
||||||
llm=llm,
|
|
||||||
tools=[web_search_tool, create_file_tool, export_files_tool],
|
|
||||||
prompt=prompt,
|
|
||||||
output_parser=parser,
|
|
||||||
)
|
|
||||||
|
|
||||||
return AgentExecutor.from_agent_and_tools(
|
|
||||||
agent=react_agent,
|
|
||||||
tools=[web_search_tool, create_file_tool, export_files_tool],
|
|
||||||
verbose=True,
|
verbose=True,
|
||||||
)
|
)
|
||||||
|
# The returned object is already an AgentExecutor
|
||||||
|
return agent
|
||||||
|
|
||||||
# Expose public names for tests
|
# Expose the executor for external use
|
||||||
__all__ = ["create_agent", "create_agent_executor", "vfs"]
|
agent_executor = create_agent_executor()
|
||||||
|
|
||||||
|
# For convenience, a small helper that runs a single prompt
|
||||||
|
|
||||||
|
def run_prompt(prompt: str) -> str:
|
||||||
|
"""Run the prompt through the agent and return the final answer."""
|
||||||
|
result = agent_executor.invoke({"input": prompt})
|
||||||
|
# The result is a dict with keys: "output" and possibly others
|
||||||
|
return result.get("output", "")
|
||||||
Reference in New Issue
Block a user