【Langchain Agent研究】SalesGPT项目介绍(五)

【Langchain Agent研究】SalesGPT项目介绍(四)-CSDN博客        

        上节课,我们分析了一下salesGPT项目里源代码的一些问题,重新写了一个运行方法,换了一个模型并修改了一些源代码开始把项目跑起来了,我们已经可以通过console和模型进行对话了。

        我们之前选的模式是不使用工具的模式,所以我们启用的是sales_conversation_utterance_chain,这节课我们尝试使用工具,也就是之前我们介绍过的sales_agent_executor和用setup_knowledge_base()方法构造的knowledge_base。

1. 运行使用工具的Agent

        我们重新写一个my_test_with_tools.py的方法,其他的地方一样,注意在构造sales_agent的时候,use_tools=True,product_catalog要改一下,用你项目本地的地址:

sales_agent = SalesGPT.from_llm(
            llm,
            verbose=True,
            use_tools=True,
            product_catalog=r"C:\Users\Administrator\SalesGPT\examples\sample_product_catalog.txt",
            salesperson_name="Ted Lasso",
            salesperson_role="Sales Representative",
            company_name="Sleep Haven",
            company_business="""Sleep Haven 
                                    is a premium mattress company that provides
                                    customers with the most comfortable and
                                    supportive sleeping experience possible. 
                                    We offer a range of high-quality mattresses,
                                    pillows, and bedding accessories 
                                    that are designed to meet the unique 
                                    needs of our customers.""",
        )

        我们运行一下这块代码,发现在我们询问产品价格后,Agent开始思考是否要使用工具(就是我们之前构造的另外一个Agent——knowledge_base,它是一个RetrievalQA类型的Chain,也可以认为是一个Agent),下面是它的思考过程,我直接用prompt模板里面的内容了:

Previous conversation history:
Ted Lasso: Hello there! This is Ted Lasso from Sleep Haven. How are you doing today?
User: 我挺好的
Ted Lasso: That's great to hear! I hope you're having a wonderful day. How can I assist you today?
User: 能介绍一下你们的产品么?
Ted Lasso:
Thought: Do I need to use a tool? Yes
Action: ProductSearch
Action Input: Sleep Haven mattresses
Observation: Sleep Haven offers a range of mattresses, including the Luxury Cloud-Comfort Memory Foam Mattress, the Classic Harmony Spring Mattress, the Plush Serenity Bamboo Mattress, and the EcoGreen Hybrid Latex Mattress. Each mattress has its own unique features and benefits, catering to different preferences and needs. The prices and sizes available for each mattress are as follows:
1. Luxury Cloud-Comfort Memory Foam Mattress:
- Price: $999
- Sizes available: Twin, Queen, King
2. Classic Harmony Spring Mattress:
- Price: $1,299
- Sizes available: Queen, King
3. Plush Serenity Bamboo Mattress:
- Price: $2,599
- Sizes available: King
4. EcoGreen Hybrid Latex Mattress:
- Price: $1,599
- Sizes available: Twin, Full
These mattresses are designed to provide comfort, support, and a restful night's sleep.
Thought: 

        这里能看到我和机器人对话的聊天记录(我使用的是中文询问),也能看到当我询问产品和价格后,我们启用了 sales_agent_executor,它开始思考是否使用它的工具——另外一个Agent进行QA查询。它的决定是YES,启用knowledge_base去查询价格。

        我们在【Langchain Agent研究】SalesGPT项目介绍(三)-CSDN博客中留下了两个遗留问题,我们在能运行项目之后再来看一下这里面的东西就清晰了:

2. CustomPromptTemplateForTools

        首先在调用CustomPromptTemplateForTools时,有三个地方需要注意,第一个是tools_getter=lambda x: tools。

prompt = CustomPromptTemplateForTools(
                template=SALES_AGENT_TOOLS_PROMPT,
                tools_getter=lambda x: tools,
                # This omits the `agent_scratchpad`, `tools`, and `tool_names` variables because those are generated dynamically
                # This includes the `intermediate_steps` variable because that is needed
                input_variables=[
                    "input",
                    "intermediate_steps",  #这是在调用tools时,会产生的中间变量,是一个list里面的一个tuple,一个是action,一个是observation
                    "salesperson_name",
                    "salesperson_role",
                    "company_name",
                    "company_business",
                    "company_values",
                    "conversation_purpose",
                    "conversation_type",
                    "conversation_history",
                ],
            )

        这一行的意思是,tools_getter这个lambda函数接收任意一个参数,返回tools。所以在后面的代码里,我改变了原来代码的输入,这完全不影响后续的结果:

  # tools = self.tools_getter(kwargs["input"])
  tools = self.tools_getter([])

         第二个是input_variables里的input是没有值的,这一点困惑了我很久,后来我才发现其实这里根本不需要input应该也是不影响代码调用的,大家可以自己试试。

         第三个是intermediate_steps,这是一个只有在代码运行中并调用了tools时才会产生的中间变量,我把它找了出来贴一下:

[(AgentAction(tool='ProductSearch', tool_input='mattress prices', log='Thought: Do I need to use a tool? Yes\nAction: ProductSearch\nAction Input: mattress prices'), 'The prices for the Sleep Haven mattresses are as follows:\n\n1. Luxury Cloud-Comfort Memory Foam Mattress: $999\n2. Classic Harmony Spring Mattress: $1,299\n3. EcoGreen Hybrid Latex Mattress: $1,599\n4. Plush Serenity Bamboo Mattress: $2,599\n\nPlease note that these prices are subject to change and may vary depending on the size of the mattress.')]

        这个是一个LIST,里面有一个tuple,tuple里面又是两个tuple ,一个是action,一个是observation,我们就用action的log和observation去构造agent_scratchpad,agent_scratchpad是构造有memory的agent必要的一个组件。至此,我们就基本搞明白了CustomPromptTemplateForTools,用它的format方法把输入的参数进行一些调整、拼接,获得一个新的prompt。但是有一点我有点不太明白的是,CustomPromptTemplateForTools这个类的format方法我并没有调用过,为啥就生效呢?这个确实不太明白,可能涉及到langchain对于prompt这块的底层设计原理,我现在还接触不到。

3. SalesConvoOutputParser

        我们来看一下这个输出解析器。这块也是之前遗留的一个难点,因为这个Parser处理的是sales_agent_executor执行后的结果,不看到具体的输出我们确实很难理解这块代码在干什么。

        我们启动代码,然后输入查询价格的指令:

Ted Lasso: Hello there! This is Ted Lasso from Sleep Haven. How are you doing today? 
say something FINE , I WANT TO KNOW YOUR PRODUCT PRICE

        首先,stage_analyzer_chain进行阶段判断,判定到了第三个阶段:

Conversation Stage ID: 3
Conversation Stage: Value proposition: Briefly explain how your product/service can benefit the prospect. Focus on the unique selling points and value proposition of your product/service that sets it apart from competitors.

        然后,AgentExecutor开始执行,AgentExecutor在读取了历史聊天记录后开始进行分析,这个是它的输出:

TEXT
Thought: Do I need to use a tool? Yes
Action: ProductSearch
Action Input: Mattress price
-------

        到这里,我们就理解了SalesConvoOutputParser代码中:

        regex = r"Action: (.*?)[\n]*Action Input: (.*)"
        match = re.search(regex, text)
        if not match:
            ## TODO - this is not entirely reliable, sometimes results in an error.
            return AgentFinish(
                {
                    "output": "I apologize, I was unable to find the answer to your question. Is there anything else I can help with?"
                },
                text,
            )
            # raise OutputParserException(f"Could not parse LLM output: `{text}`")
        action = match.group(1)
        action_input = match.group(2)
        return AgentAction(action.strip(), action_input.strip(" ").strip('"'), text)

        regex = r"Action: (.*?)[\n]*Action Input: (.*)" 是一个正则表达式,这个正则表达式可以用来匹配文本中以"Action:"开头,接着是动作内容,然后是零个或多个换行符,最后以"Action Input:"开头,接着是动作输入内容的部分。后面做的事情就是要用这个正则表达式去查询TEXT内容,去把"Action:"和"Action Input:"后面的东西提取出来,并赋值给action和action_input。

        这是AgentExecutor第一轮的输出,然后到第二轮的输出:

TEXT
Ted Lasso: The prices for our Sleep Haven mattresses range from $999 to $2,599, depending on the model you choose. We have the Classic Harmony Spring Mattress for $1,299, the Luxury Cloud-Comfort Memory Foam Mattress for $999, the EcoGreen Hybrid Latex Mattress for $1,599, and the Plush Serenity Bamboo Mattress for $2,599. These prices reflect the high-quality materials and craftsmanship that go into creating our mattresses. Is there a specific model you are interested in?
-------

        这个时候,已经通过调用工具进行了知识库查询,获得了这段TEXT,然后我们就理解了这段代码的作用:

        if f"{self.ai_prefix}:" in text:
            return AgentFinish(
                {"output": text.split(f"{self.ai_prefix}:")[-1].strip()}, text
            )

         就是如果发现了Ted Lasso:为开头的输出,那就表明AgentExecutor已经获得了执行结果,代表可以返回AgentFinish,代表这个流程结束了。

 4.结束语

        至此,我们就基本掌握了SalesGPT的基本原理,也了解了它的核心代码逻辑和一些有难点的地方,这对于我们理解多Agent系统,对话阶段判断和prompt与parser的内容组装调整有巨大的好处。

        下一步,我们将尝试把我们之前构造的聊天机器人加入多Agent系统,让他可以根据用户对话的情况进行分析,给用户推销适配的旅游产品。

你可能感兴趣的:(salesGPT研究拆解,langchain,人工智能,prompt,SalesGPT,Agent,LLM)