LangChain自动化生成指令数据集

基础

  1. Agent和AgentExecutor的区别
  2. AgentExecutor.from_agent_and_tools()和AgentExecutor()的区别
  3. PromptTemplate和ChatPromptTemplate的区别
  4. 如何让LLM输出Json格式
  5. 如何让LLM输出自定义格式
  6. Agent执行的全过程

LangChain库函数

Pydantic:确保数据符合预期的格式和结构

问题

  1. Unhashable Type Tool when using custom tools

Json格式输出

from langchain_community.chat_models import ChatZhipuAI
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain.prompts import PromptTemplate
from langchain_core.output_parsers import JsonOutputParser

from pprint import pprint

llm = ChatZhipuAI(
    model="glm-4",
    api_key="eb9aed8db44efa3b428072914bc5063e.Vr33yNfWV4QTnUy6",
)

class Ans(BaseModel):
    NAME: list = Field(description="有名的诗人的名字")
    POEM: str = Field(description="诗词")

parser = JsonOutputParser(pydantic_object=Ans)

prompt = PromptTemplate(
    template="{format_instructions}\n{query}",
    input_variables=["query"],
    partial_variables={"format_instructions": parser.get_format_instructions()},
)
model = prompt|llm|parser
print(model.invoke({"query": "有名的诗人和他们的诗,请说中文"}))

基于Json的信息检索

V1.0

import os
import json
import logging
from openai import AzureOpenAI

from langchain_community.chat_models import ChatZhipuAI
from langchain.agents import (AgentExecutor,
                              create_react_agent)
from langchain_core.tools import tool

# 输出
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_core.prompts import PromptTemplate,ChatPromptTemplate

logging.basicConfig(filename="LangChain.log",  # 将日志保存到filename文件中 
                    level=logging.DEBUG)  # DEBUG及以上的日志信息都会显示

class Inst(BaseModel):
    Key:str=Field(description="数字编号")
    Value:dict=Field(description="Key所对应的Value")

parser = JsonOutputParser(pydantic_object=Inst)

@tool
def search(view:str)->dict:
    """
    在"/home/zym/桌面/WORK/Entity.json"中有若干字典
    找到键值与view相同的字典,返回键值view对应的value
    """
    with open("/home/zym/桌面/WORK/Entity.json","r") as f:
        data=json.load(f)
    return data[view]


prompt= """
        你的任务是根据接受的参数view作为字典的键,使用工具中的search在JSON文件中找到对应的值并返回
        返回格式为Dict(Key:view,Value:search(view))
        参数:{view}
        """

tools=[search]
tool_names=[search]
inputs = PromptTemplate(
            template="{format_instructions}\n{tools}\n{tool_names}\n{query}\n{agent_scratchpad}",
            input_variables=["query"],
            partial_variables={"format_instructions": parser.get_format_instructions()},
        )

agent = create_react_agent(zhipu, tools, inputs)
agent_executor=AgentExecutor(agent=agent,tools=tools,verbose=True,parser=parser,handle_parsing_errors=True)
print(agent_executor.invoke({"query":prompt.format(view="1019-00245"),"tools":tools,"tool_names":tool_names}))

问题1:没有任何信息输出,最终“Agent stopped due to iteration limit or time limit”:工具并没有被调用

Since I cannot directly execute the search function as it’s not accessible in this environment, I will show you how the formatted output should look like

在这里插入图片描述


猜测1:定义输出Parser

  • 改了但是没用
class Inst(BaseModel):
    Key:str=Field(description="view的字段")
    Value:dict=Field(description="Json文件中键值为view时所对应的字典")

parser = JsonOutputParser(pydantic_object=Inst)

猜测2:ReAct Agent无法调用工具

V2.0

import os
import json
import logging
from openai import AzureOpenAI
from langchain.agents import (AgentExecutor,
                              create_react_agent,)
from typing import List
from langchain.tools.base import BaseTool
# 输出
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.pydantic_v1 import BaseModel, Field, validator
from langchain_core.prompts import PromptTemplate

logging.basicConfig(filename="LangChain.log",
                    level="DEBUG") 

class Inst(BaseModel):
    View:str=Field(description="Input的字段")
    Action:list=Field(description="选择的动作")
    Param:List[dict]=Field(description="字典中的键为参数类别,值为实例")
    Instruction:str=Field(description="最终形成的指令")

parser = JsonOutputParser(pydantic_object=Inst)

os.environ["OPENAI_API_KEY"] = "2171af6f71075a0bd567a23340506b70"
REGION = "australiaeast"
API_BASE = "https://api.tonggpt.mybigai.ac.cn/proxy"
ENDPOINT = f"{API_BASE}/{REGION}"
llm = AzureOpenAI(
            api_key=os.environ.get("OPENAI_API_KEY"),
            api_version="2024-02-01",
            azure_endpoint=ENDPOINT,
        )

class FunctionalTool(BaseTool):
    name:str = ""
    description:str = ""

class MySearchEntity(FunctionalTool):
    name="MySearchEntity"
    description="当需要知道这个场景包含什么以及相对位置关系的时候,执行这个函数,传入的参数只能是一个字符串"

    def _run(self,view:str):
        """使用工具"""
        print("乌拉呀哈 呀哈乌拉")
        with open("/home/zym/桌面/WORK/Entity.json","r",encoding="utf-8") as f:
            data=json.load(f)
        
        # 标准化输入参数
        return data[view.strip("'\n\nObservation'")]
     
    async def _arun(self,view: str)-> str:
        """异步使用工具"""
        raise NotImplementedError("custom_search does not support async") 
    

class MySearchParam(FunctionalTool):
    name="MySearchParam"
    description="当需要知道这个可以使用的动作包含什么以及参数的时候,执行这个函数"

    def _run(self,*args):
        """使用工具"""
        print("咿呀哈")
        with open("/home/zym/桌面/WORK/Gen/Param.json","r",encoding="utf-8") as f:
            data=json.load(f)
        
        return data
        
    async def _arun(self,*args)-> str:
        """异步使用工具"""
        raise NotImplementedError("custom_search does not support async") 

prompt=PromptTemplate(
                input_variables=['agent_scratchpad', 'input', 'tool_names', 'tools'], 
                partial_variables={"format_instructions":parser.get_format_instructions()},
                template='''
                    你是一个家务机器人,你需要知道场景中有什么物品,以及你可以执行哪些动作
                    你可以使用如下工具:{tools}
                    
                    使用如下格式:
            
                    Task: 选择工具完成任务
                    Thought: 你应该思考接下来如何去完成任务
                    Action: {tool_names}
                    Action Input: 一个字符串
                    Observation: 执行动作得到的结果
                    ... (Thought/Action/Action Input/Observation 可以重复N次)
                    Thought: 我知道了最终的答案
                    Final Answer: 对应任务所需要的答案res
                
                    开始!
                    Task: 首先你想知道这个场景里有什么物品,于是传入参数{input};
                        在返回值res中,你对里面的物品产生了兴趣,于是你需要使用工具查询可执行动作及参数;
                        当你选择了物品和动作后,利用它们组成一条指令。
                        
                    Thought:{agent_scratchpad}
                    ''')
                    
from langchain.agents import load_tools

tools = load_tools([],llm=llm)
tools = tools+[MySearchEntity(),MySearchParam()]
tool_names=["MySearchEntity","MySearchParam"]


agent = create_react_agent(zhipu, 
                           tools, 
                           prompt,
                           )

agent_executor=AgentExecutor(agent=agent,
                             tools=tools,
                             verbose=True,
                             handle_parsing_errors=True,
                             )

res=agent_executor.invoke({"input":prompt.format(input="1019-00245",
                                                   tools=tools,
                                                   tool_names=tool_names,
                                                   agent_scratchpad=""),
                             "tools":tools,
                             "tool_names":tool_names,
                             "agent_scratchpad":""})

问题1:没有结构化的输出

在这里插入图片描述

问题2:不会自动停止,出现了反复调用工具的情况

  • 通过修改prompt可以改善
prompt=PromptTemplate(
                input_variables=['agent_scratchpad', 'input', 'tool_names', 'tools'], 
                partial_variables={"format_instructions":parser.get_format_instructions()},
                template='''
                    你是一个家务机器人,要依据指令完成生活中的任务。
                    你可以使用如下工具:{tools}
                    
                    当你还未完成任务时,使用如下格式:
                    """
                    Thought: 我是否需要工具?是
                    Action: {tool_names}
                    Action Input: 一个字符串
                    Observation:如果调用了工具,则输出执行动作得到的结果
                    """

                    当你完成所有任务并生成指令后,你必须使用以下格式,我给出一个例子:
                    """
                    Thought:我是否需要工具?不
                    Final Answer:{format_instructions}
                    Example:
                            "Action":["取东西吃","清洁"],
                            "Param":[("food": "Bread_000"),
                                      ("tool":"Sponge_000,"object":"Diningdesk_002")]
                            "Instruction":"请把面包吃完,之后使用海绵把餐桌清洁干净"
                            
                    """
                
                    开始!
                    Task: 请依次完成以下任务:
                        1.你想知道这个生活场景里包含什么物品,于是调用工具并传入字符串{input};
                        2.在返回值res中,你对里面的1~3物品产生了兴趣,于是你需要使用工具查询对你所感兴趣的物品可以执行的1~3个动作;
                        3.你想知道这1~3个动作需要什么参数,于是你针对每个动作分别调用工具并把动作名称传入
                        4.你想知道你的身份,于是你调用工具
                        5.根据你选择的物品、动作、参数,代入你身份可能会做的事情,模仿身份的语气,给出一条必须为中文的指令
                        
                    Thought:{agent_scratchpad}
                    ''')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值