LangChain项目agent源码梳理(一)

LangChain项目agent源码梳理(一)

agent概念

  1. 什么是agent?agent是输入处理模块、llm作为大脑、tools作为手脚,memory用于状态保持,并提供复盘优化的智能体。

源码梳理(基于langchain0.3.23版本)

  1. 入口函数
# langchain.agents.react.agent.py
def create_react_agent(
    llm: BaseLanguageModel,
    tools: Sequence[BaseTool],
    prompt: BasePromptTemplate,
    output_parser: Optional[AgentOutputParser] = None,
    tools_renderer: ToolsRenderer = render_text_description,
    *,
    stop_sequence: Union[bool, List[str]] = True,
) -> Runnable:
    ...
  1. 重要参数:tools
# langchain_core.tools.base.py定义了BaseTool,以内置的搜索引擎tool为例
# langchain_community.tools.ddg_search.tool.py
class DuckDuckGoSearchRun(BaseTool):
    # BaseTool的子类,覆写了一些属性,封装了api调用
    api_wrapper: DuckDuckGoSearchAPIWrapper = Field(
        default_factory=DuckDuckGoSearchAPIWrapper
    )

    # 核心函数
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return self.api_wrapper.run(query)
  1. 重要参数:prompt
    prompt需要包含一些必要信息:
# Prompt:
# 
#         The prompt must have input keys:
#             * `tools`: contains descriptions and arguments for each tool.
#             * `tool_names`: contains all tool names.
#             * `agent_scratchpad`: contains previous agent actions and tool outputs as a string.

也可以使用langchain hub中的prompt模板,用于更好的简化输入,以hub中比较热门的prompt-maker为例:

# prompt-maker在hub中的url:https://smith.langchain.com/hub/hardkothari/prompt-maker
# 其主要用于简化用户的输入,如“生成一篇关于宠物的论文”,那么maker会将输入扩展,以更好的符合大模型的结构化输入
from langchain import hub 
prompt_maker = hub.pull("prompt-maker", include_model=True,
                        api_key="hub账号的key",
                        api_url="https://smith.langchain.com/hub/hardkothari/prompt-maker")
  1. 重要参数:output_parser
# langchain.agents.agent.py  
# AgentOutputParser类有多个子类,均位于langchain.agents下,如
# langchain.agents.output_parsers.xml.py中的
class XMLAgentOutputParser(AgentOutputParser)

# langchain.agents.structured_chat.output_parser.py
class StructuredChatOutputParser(AgentOutputParser)
  1. 简单demo,创建agent
from pydantic import SecretStr
from langchain import hub 
from langchain.agents.react import agent 
from langchain.prompts import PromptTemplate
from langchain.agents.structured_chat.output_parser import StructuredChatOutputParser
from langchain_community.chat_models.tongyi import ChatTongyi
from langchain_community.tools.ddg_search import DuckDuckGoSearchRun

llm = ChatTongyi(model="deepseek-r1", api_key=SecretStr('YOUR_API_KEY'))
tools = [DuckDuckGoSearchRun()]
hub_maker_prompt = hub.pull(
    "prompt-maker",
    include_model=True,
    api_key="",
    api_url=""
)
custom_prompt = f"""
{hub_maker_prompt.template}

你拥有以下工具:
{{{{tools}}}}

工具名称列表:{{{{tool_names}}}}

按照以下格式执行:
Question: 需要回答的问题
Thought: 思考过程(必须分析是否需要使用工具)
Action: 选择工具(必须是 [{{{{tool_names}}}}] 之一)
Action Input: 工具输入参数
Observation: 工具返回结果
...(可重复多次)
Thought: 现在可以生成最终答案
Final Answer: 最终回答

开始!

Question: {{{{input}}}}
{{{{agent_scratchpad}}}}"""

text_prompt = PromptTemplate(
    input_variables=["input", "tools", "tool_names", "agent_scratchpad"],
    template=custom_prompt
)
out = StructuredChatOutputParser()

text_agent = agent.create_react_agent(
    llm=llm,
    tools=tools,
    prompt=text_prompt,
    output_parser=out
)

进一步展开说明

  1. langchain包含很多组件,上述的tools, prompt, output_parser等都有丰富的组件可以选用,如:
工具类名称功能描述输入参数典型场景
BaseTool所有工具的基类自定义开发自定义工具时继承使用
StructuredTool结构化参数工具args_schema (Pydantic)需要严格参数校验的场景
DuckDuckGoSearchRunDuckDuckGo 搜索query: str实时信息检索(如新闻、赛事结果)
prompt类名称用途关键参数特点
BasePromptTemplate所有prompt的基类invoke / format_template开发自定义prompt时继承
StringPromptTemplate动态渲染生成模版stringformat_template支持f-string和jinja2模版引擎
ChatPromptTemplate对话式提示messages支持组合system,ai,human等message类型
parser类名称作用输出类型特点
BaseOutputParser所有output的基类
StringOutputParser原始字符串输出str直接返回LLM生成的文本
ChatOutputParser将输出转换为agentAction 或 agentFinish对象agentAction用于chat agent使用
  1. 需要结合业务的特点选择合适的组件工具,或者自定义实现,后续慢慢补充。
### 关于 LangChain Agent 的实际项目案例与示例 LangChain 提供了种灵活的方式来构建和管理 Agents,使其能够通过调用外部工具完成复杂的任务。以下是几个常见的实战项目案例及其代码实现。 #### 1. 使用 OpenAI 函数代理创建简单问答系统 此示例展示了如何利用预定义的提示模板快速设置个基于函数的代理: ```python from langchain.agents import load_tools, initialize_agent from langchain.llms import OpenAI # 初始化 LLM 和 工具链 llm = OpenAI(temperature=0) tools = load_tools(["serpapi", "llm-math"], llm=llm) # 创建 agent 并指定其行为模式 agent_chain = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True) # 测试运行 result = agent_chain.run("谁赢得了2022年世界杯?") print(result) # 输出结果并展示推理过程[^1] ``` 上述代码片段中,`initialize_agent` 方法被用来初始化个零样本反应描述型代理 (Zero-Shot React Description),它可以根据上下文动态决定使用哪些工具来解决问题。 --- #### 2. 构建多步骤 SQL 查询解析器 如果目标是从自然语言查询转换成数据库操作,则可以考虑如下方式: ```python from langchain.agents.agent_toolkits import create_sql_agent from langchain.sql_database import SQLDatabase from langchain.llms.openai import OpenAI from langchain.agents import AgentExecutor from langchain.agents.agent_types import AgentType db_url = "sqlite:///your-database.db" database = SQLDatabase.from_uri(db_url) llm = OpenAI(temperature=0) sql_agent_executor = create_sql_agent( llm=llm, toolkit=create_sql_agent(llm=llm, db=database), agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True ) response = sql_agent_executor.run("告诉我销售额最高的产品是什么?") print(response) # 返回对应的产品名称以及销售金额[^2] ``` 这里的关键在于 `create_sql_agent` 函数的应用,它可以自动将用户的提问转化为针对特定关系型数据库的有效SQL语句执行请求。 --- #### 3. 综合多种工具解决复杂问题 对于更高级别的需求——例如需要结合搜索引擎、文档检索以及其他自定义插件共同工作时,可以通过组合不同类型的 agents 来达成目的: ```python from langchain.document_loaders import DirectoryLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.embeddings.openai import OpenAIEmbeddings from langchain.vectorstores import Chroma from langchain.chains.question_answering import load_qa_chain from langchain.prompts.prompt import PromptTemplate from langchain.chat_models import ChatOpenAI import os loader = DirectoryLoader('./data', glob='*.txt') documents = loader.load() text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0) texts = text_splitter.split_documents(documents) embeddings = OpenAIEmbeddings() docsearch = Chroma.from_documents(texts, embeddings).as_retriever(search_kwargs={"k": 1}) template = """Use the following pieces of context to answer the question at the end. {context} Question: {question} Answer:""" QA_CHAIN_PROMPT = PromptTemplate(input_variables=["context", "question"], template=template) qa_chain = load_qa_chain(ChatOpenAI(), chain_type="stuff", prompt=QA_CHAIN_PROMPT) def complex_query(query): docs = docsearch.get_relevant_documents(query) result = qa_chain({"input_documents": docs, "question": query}, return_only_outputs=True)["output_text"] return result answer = complex_query("解释下量子力学的基础原理.") print(answer) # 展现详细的解答内容[^3] ``` 这段脚本首先加载本地文件夹中的所有文本资料作为知识库的部分;接着采用嵌入向量存储技术建立索引结构以便高效查找相似段落;最后再借助定制化的大规模生成模型给出精确答案。 --- #### 性能优化技巧 为了提高效率减少延迟时间,在设计阶段就应该考虑到以下几个方面: - **缓存机制**:重复计算的结果可以直接读取而无需再次求解; - **异步处理**:允许并发访问多个资源从而加快整体进度; - **简化逻辑流**:去除不必要的中间环节以降低开销成本。[^4] --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值