(转载分享)LangChain中Agent的一个实用案例

import re
from typing import List, Union
import textwrap
import time

from langchain.agents import (
    Tool,
    AgentExecutor,
    LLMSingleActionAgent,
    AgentOutputParser,
)
from langchain.prompts import StringPromptTemplate
from langchain import OpenAI, LLMChain
from langchain.schema import AgentAction, AgentFinish
from langchain.prompts import PromptTemplate

from langchain.llms.base import BaseLLM


CONTEXT_QA_TMPL = """
根据以下提供的信息,回答用户的问题
信息:{context}

问题:{query}
"""
CONTEXT_QA_PROMPT = PromptTemplate(
    input_variables=["query", "context"],
    template=CONTEXT_QA_TMPL,
)


def output_response(response: str) -> None:
    if not response:
        exit(0)
    for line in textwrap.wrap(response, width=60):
        for word in line.split():
            for char in word:
                print(char, end="", flush=True)
                time.sleep(0.1)  # Add a delay of 0.1 seconds between each character
            print(" ", end="", flush=True)  # Add a space between each word
        print()  # Move to the next line after each line is printed
    print("----------------------------------------------------------------")


class FugeDataSource:
    def __init__(self, llm: BaseLLM):
        self.llm = llm

    def find_product_description(self, product_name: str) -> str:
        """模拟公司产品的数据库"""
        product_info = {
            "好快活": "好快活是一个营销人才平台,以社群+公众号+小程序结合的运营模式展开,帮助企业客户连接并匹配充满才华的营销人才。",
            "Rimix": """Rimix通过采购流程数字化、完备的项目数据存储记录及标准的供应商管理体系,帮助企业实现采购流程, 透明合规可追溯,大幅节约采购成本。Rimix已为包括联合利华,滴滴出行等多家广告主提供服务,平均可为客户节约采购成本30%。""",
            "Bid Agent": "Bid Agent是一款专为中国市场设计的搜索引擎优化管理工具,支持5大搜索引擎。Bid Agent平均为广告主提升18%的投放效果,同时平均提升47%的管理效率。目前已为阳狮广告、GroupM等知名4A公司提供服务与支持。",
        }
        return product_info.get(product_name, "没有找到这个产品")

    def find_company_info(self, query: str) -> str:
        """模拟公司介绍文档数据库,让llm根据抓取信息回答问题"""
        context = """
        关于产品:"让广告技术美而温暖"是复歌的产品理念。在努力为企业客户创造价值的同时,也希望让使用复歌产品的每个人都能感受到技术的温度。
        我们关注用户的体验和建议,我们期待我们的产品能够给每个使用者的工作和生活带来正面的改变。
        我们崇尚技术,用科技的力量使工作变得简单,使生活变得更加美好而优雅,是我们的愿景。
        企业文化:复歌是一个非常年轻的团队,公司大部分成员是90后。
        工作上,专业、注重细节、拥抱创新、快速试错。
        协作中,开放、坦诚、包容、还有一点点举重若轻的幽默感。
        以上这些都是复歌团队的重要特质。
        在复歌,每个人可以平等地表达自己的观点和意见,每个人的想法和意愿都会被尊重。
        如果你有理想,并拥有被理想所驱使的自我驱动力,我们期待你的加入。
        """
        prompt = CONTEXT_QA_PROMPT.format(query=query, context=context)
        return self.llm(prompt)


AGENT_TMPL = """按照给定的格式回答以下问题。你可以使用下面这些工具:

{tools}

回答时需要遵循以下用---括起来的格式:

---
Question: 我需要回答的问题
Thought: 回答这个上述我需要做些什么
Action: ”{tool_names}“ 中的其中一个工具名
Action Input: 选择工具所需要的输入
Observation: 选择工具返回的结果
...(这个思考/行动/行动输入/观察可以重复N次)
Thought: 我现在知道最终答案
Final Answer: 原始输入问题的最终答案
---

现在开始回答,记得在给出最终答案前多按照指定格式进行一步一步的推理。

Question: {input}
{agent_scratchpad}
"""


class CustomPromptTemplate(StringPromptTemplate):
    template: str  # 标准模板
    tools: List[Tool]  # 可使用工具集合

    def format(self, **kwargs) -> str:
        """
        按照定义的 template,将需要的值都填写进去。

        Returns:
            str: 填充好后的 template。
        """
        intermediate_steps = kwargs.pop("intermediate_steps")  # 取出中间步骤并进行执行
        thoughts = ""
        for action, observation in intermediate_steps:
            thoughts += action.log
            thoughts += f"\nObservation: {observation}\nThought: "
        kwargs["agent_scratchpad"] = thoughts  # 记录下当前想法
        kwargs["tools"] = "\n".join(
            [f"{tool.name}: {tool.description}" for tool in self.tools]
        )  # 枚举所有可使用的工具名+工具描述
        kwargs["tool_names"] = ", ".join(
            [tool.name for tool in self.tools]
        )  # 枚举所有的工具名称
        cur_prompt = self.template.format(**kwargs)
        print(cur_prompt)
        return cur_prompt


class CustomOutputParser(AgentOutputParser):
    def parse(self, llm_output: str) -> Union[AgentAction, AgentFinish]:
        """
        解析 llm 的输出,根据输出文本找到需要执行的决策。

        Args:
            llm_output (str): _description_

        Raises:
            ValueError: _description_

        Returns:
            Union[AgentAction, AgentFinish]: _description_
        """
        if "Final Answer:" in llm_output:  # 如果句子中包含 Final Answer 则代表已经完成
            return AgentFinish(
                return_values={"output": llm_output.split("Final Answer:")[-1].strip()},
                log=llm_output,
            )

        regex = r"Action\s*\d*\s*:(.*?)\nAction\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)"  # 解析 action_input 和 action
        match = re.search(regex, llm_output, re.DOTALL)
        if not match:
            raise ValueError(f"Could not parse LLM output: `{llm_output}`")
        action = match.group(1).strip()
        action_input = match.group(2)

        return AgentAction(
            tool=action, tool_input=action_input.strip(" ").strip('"'), log=llm_output
        )


if __name__ == "__main__":
    ## set api token in terminal
    llm = OpenAI(temperature=0, model_name="gpt-3.5-turbo")

    fuge_data_source = FugeDataSource(llm)
    tools = [
        Tool(
            name="查询产品名称",
            func=fuge_data_source.find_product_description,
            description="通过产品名称找到产品描述时用的工具,输入应该是产品名称",
        ),
        Tool(
            name="复歌科技公司相关信息",
            func=fuge_data_source.find_company_info,
            description="当用户询问公司相关的问题,可以通过这个工具了解相关信息",
        ),
    ]
    agent_prompt = CustomPromptTemplate(
        template=AGENT_TMPL,
        tools=tools,
        input_variables=["input", "intermediate_steps"],
    )
    output_parser = CustomOutputParser()

    llm_chain = LLMChain(llm=llm, prompt=agent_prompt)

    tool_names = [tool.name for tool in tools]
    agent = LLMSingleActionAgent(
        llm_chain=llm_chain,
        output_parser=output_parser,
        stop=["\nObservation:"],
        allowed_tools=tool_names,
    )

    agent_executor = AgentExecutor.from_agent_and_tools(
        agent=agent, tools=tools, verbose=True
    )

    while True:
        try:
            user_input = input("请输入您的问题:")
            response = agent_executor.run(user_input)
            output_response(response)
        except KeyboardInterrupt:
            break

这是一个很不错的Agent实战案例,作为一个大模型小菜鸟可以学习很多实战思想。

链接:LangChain中Agent的一个实用案例 - 知乎

### LangChainAgent 的架构与工作原理 #### 1. **Agent 的核心概念** Agent 是一种基于大型语言模型 (LLM) 的推理机制,其主要功能是通过一系列工具和逻辑推导来解决复杂问题。它的设计目的是让 LLM 不仅能够生成自然语言响应,还能动态调用外部工具或 API 来增强自身的功能性[^2]。 #### 2. **Agent 的组成结构** LangChain 中的 Agent 主要由以下几个部分构成: - **Language Model (LLM)** 这是一个强大的预训练模型,负责理解输入并生成相应的输出。它是整个 Agent 推理过程的核心大脑[^3]。 - **Tools (工具集)** Tools 提供了一系列可以被 Agent 调用的功能模块,例如搜索引擎查询、数据库访问或其他自定义函数。这些工具扩展了 LLM 的能力范围[^1]。 - **Prompt Template (提示模板)** Prompt Template 定义了如何向 LLM 输入数据的形式化描述。它通常包含了上下文信息、可用工具列表以及用户的实际请求。 - **Memory (记忆存储)** Memory 组件允许 Agent 记录之前的交互历史,从而实现更连贯的对话体验。这对于多轮次的任务尤为重要。 #### 3. **Agent 的工作流程** 当用户提交一个问题给 Agent 后,以下是典型的处理步骤: 1. 用户提供初始指令; 2. 基于当前状态构建 prompt 并发送至 LLM; 3. LLM 返回下一步行动计划或者直接给出答案; 4. 如果返回的是行动计划,则执行相应 tool,并收集反馈结果; 5. 将新获得的信息重新注入到循环中继续迭代直至满足终止条件为止。 #### 4. **使用方法概述** 为了创建一个简单的 Agent 应用程序,在 Python 环境下可按照以下方式操作: ```python from langchain.agents import initialize_agent, Tool from langchain.llms import OpenAI from langchain.tools import DuckDuckGoSearchRun # 初始化基础组件 llm = OpenAI(temperature=0) search_tool = DuckDuckGoSearchRun() tools = [ Tool( name="Search", func=search_tool.run, description="Useful for when you need to search the web." ) ] agent_chain = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True) result = agent_chain.run("What is the capital of France?") print(result) ``` 上述代码片段展示了如何快速搭建具备网络搜索能力的小型 Agent 实例。 #### 5. **示例分析** 假设我们希望开发一款能自动回答地理类常识问答的应用程序,那么就可以利用类似下面这样的配置文件来进行设置: ```yaml name: GeographyQA description: A simple geography question answering system. version: '0.1' toolkit: tools: - type: duckduckgo_search params: max_results: 3 model_config: model_name: gpt-3.5-turbo memory_type: conversation_buffer_memory max_iterations: 5 early_stopping_method: generate_until_stop ``` 此 YAML 文件明确了所使用的具体参数选项,便于后续维护调整。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值