langchain 之 Tools 多案例使用(一)

原文:langchain 之 Tools 多案例使用(一) - 简书

ATTENTION:

  1. 如果采用 openai 的接口,需要走代理,本文采用 proxychains 进行设置。
  2. 开启 debug 模式后,能看到更多的输出信息。
import langchain
langchain.debug = True

1. Tools

参数如下。

  • name (str), 必填参数,并且在提供给代理的一组工具中必须是唯一的。
  • description (str), 可选参数,但推荐使用,因为它由代理用于确定工具的使用。描述的越清晰,LLM采用工具完成的任务越准确!
  • return_direct (bool), defaults to False
  • args_schema (Pydantic BaseModel), 可选参数,但推荐使用,可用于提供更多信息(例如,few-shot examples)或验证预期参数( validation for expected parameters)。
  • func (function), 必填,传入 tool 需要执行的操作。可以是 class、function等等。
  • coroutine (function), 可选参数,传入参数与 func 一样,但是需要用 async 修饰。

典型函数:

def read_previous_db(words:str)....class CInput(pydantic.BaseModel):question: str = pydantic.Field()tool = Tool.from_function(func=read_previous_db,name="previous_records",description="用于回答与用户的历史对话信息,直接传入用户的问题,将查询后的结果再用 xx 工具回答给用户"# args_schema=CInput,)

1.1 调用自定义函数(局部代码)

如下面代码所示,可以通过接口使用 SQL 语句查询数据库

import requests
from typing import List, Dict, Any
import jsondef vocab_lookup(search: str,entity_type: str = "item",url: str = "https://www.wikidata.org/w/api.php",user_agent_header: str = wikidata_user_agent_header,srqiprofile: str = None,
) -> Optional[str]:headers = {"Accept": "application/json"}if wikidata_user_agent_header is not None:headers["User-Agent"] = wikidata_user_agent_headerif entity_type == "item":srnamespace = 0srqiprofile = "classic_noboostlinks" if srqiprofile is None else srqiprofileelif entity_type == "property":srnamespace = 120srqiprofile = "classic" if srqiprofile is None else srqiprofileelse:raise ValueError("entity_type must be either 'property' or 'item'")params = {"action": "query","list": "search","srsearch": search,"srnamespace": srnamespace,"srlimit": 1,"srqiprofile": srqiprofile,"srwhat": "text","format": "json",}response = requests.get(url, headers=headers, params=params)if response.status_code == 200:title = get_nested_value(response.json(), ["query", "search", 0, "title"])if title is None:return f"I couldn't find any {entity_type} for '{search}'. Please rephrase your request and try again"# if there is a prefix, strip it offreturn title.split(":")[-1]else:return "Sorry, I got an error. Please try again."def run_sparql(query: str,url="https://query.wikidata.org/sparql",user_agent_header: str = wikidata_user_agent_header,
) -> List[Dict[str, Any]]:headers = {"Accept": "application/json"}if wikidata_user_agent_header is not None:headers["User-Agent"] = wikidata_user_agent_headerresponse = requests.get(url, headers=headers, params={"query": query, "format": "json"})if response.status_code != 200:return "That query failed. Perhaps you could try a different one?"results = get_nested_value(response.json(), ["results", "bindings"])return json.dumps(results)sql_result = run_sparql("SELECT (COUNT(?children) as ?count) WHERE { wd:Q1339 wdt:P40 ?children . }")
print(sql_result)### Agent wraps the tools
from langchain.agents import (Tool,AgentExecutor,LLMSingleActionAgent,AgentOutputParser,
)# Define which tools the agent can use to answer user queries
tools = [Tool(name="ItemLookup",func=(lambda x: vocab_lookup(x, entity_type="item")),description="useful for when you need to know the q-number for an item",),Tool(name="PropertyLookup",func=(lambda x: vocab_lookup(x, entity_type="property")),description="useful for when you need to know the p-number for a property",),Tool(name="SparqlQueryRunner",func=run_sparql,description="useful for getting results from a wikibase",),
]

或者传入构造的函数,比如下面传入的 multi-input,直接传入参数 String 然后分解参数。

def multiplier(a, b):return a * bdef parsing_multiplier(string):a, b = string.split(",")return multiplier(int(a), int(b))
llm = OpenAI(temperature=0)
tools = [Tool(name="Multiplier",func=parsing_multiplier,description="useful for when you need to multiply two numbers together. The input to this tool should be a comma separated list of numbers of length two, representing the two numbers you want to multiply together. For example, `1,2` would be the input if you wanted to multiply 1 by 2.",)
]

https://python.langchain.com/docs/modules/agents/tools/multi_input_tool
或者自定义类。


import yfinance as yf
from datetime import datetime, timedeltadef get_current_stock_price(ticker):"""Method to get current stock price"""ticker_data = yf.Ticker(ticker)recent = ticker_data.history(period="1d")return {"price": recent.iloc[0]["Close"], "currency": ticker_data.info["currency"]}def get_stock_performance(ticker, days):"""Method to get stock price change in percentage"""past_date = datetime.today() - timedelta(days=days)ticker_data = yf.Ticker(ticker)history = ticker_data.history(start=past_date)old_price = history.iloc[0]["Close"]current_price = history.iloc[-1]["Close"]return {"percent_change": ((current_price - old_price) / old_price) * 100}# res1 = get_current_stock_price("MSFT")
# print(res1)
# res2 = get_stock_performance("MSFT", 30)
# print(res2)from typing import Type
from pydantic import BaseModel, Field
from langchain.tools import BaseToolclass CurrentStockPriceInput(BaseModel):"""Inputs for get_current_stock_price"""ticker: str = Field(description="Ticker symbol of the stock")class CurrentStockPriceTool(BaseTool):name = "get_current_stock_price"description = """Useful when you want to get current stock price.You should enter the stock ticker symbol recognized by the yahoo finance"""args_schema: Type[BaseModel] = CurrentStockPriceInputdef _run(self, ticker: str):price_response = get_current_stock_price(ticker)return price_responsedef _arun(self, ticker: str):raise NotImplementedError("get_current_stock_price does not support async")class StockPercentChangeInput(BaseModel):"""Inputs for get_stock_performance"""ticker: str = Field(description="Ticker symbol of the stock")days: int = Field(description="Timedelta days to get past date from current date")class StockPerformanceTool(BaseTool):name = "get_stock_performance"description = """Useful when you want to check performance of the stock.You should enter the stock ticker symbol recognized by the yahoo finance.You should enter days as number of days from today from which performance needs to be check.output will be the change in the stock price represented as a percentage."""args_schema: Type[BaseModel] = StockPercentChangeInputdef _run(self, ticker: str, days: int):response = get_stock_performance(ticker, days)return responsedef _arun(self, ticker: str):raise NotImplementedError("get_stock_performance does not support async")from langchain.agents import AgentType
from langchain.chat_models import ChatOpenAI
from langchain.agents import initialize_agentllm = ChatOpenAI(model="gpt-3.5-turbo-0613", temperature=0)tools = [CurrentStockPriceTool(), StockPerformanceTool()]agent = initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS, verbose=True)res3 = agent.run("What is the current price of Microsoft stock? How it has performed over past 6 months?"
)
print(res3)

至于这里为什么 agent=AgentType.OPENAI_FUNCTIONS ?文章第二部分会提到。

1.2 搜索引擎等第三方工具

直接通过 serp 进行接口调用,可点击 https://serpapi.com/ 进行查看所有支持的接口类型,也包括百度,涉及到接口问题,需要添加 api_key。

# 需要添加 os.environ["SERPAPI_API_KEY"] = ""# Load the tool configs that are needed.
search = SerpAPIWrapper()
llm_math_chain = LLMMathChain(llm=llm, verbose=True)
tools = [Tool.from_function(func=search.run,name="Search",description="useful for when you need to answer questions about current events"# coroutine= ... <- you can specify an async method if desired as well),
]

也可直接使用 langchain 自带内部的接口工具。

llm = OpenAI(temperature=0)
tools = load_tools(["wikipedia", "llm-math", "terminal"], llm=llm)
agent = initialize_agent(tools,llm,agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
)

from llama_index.tools.ondemand_loader_tool import OnDemandLoaderTool
from llama_index.readers.wikipedia import WikipediaReader
from typing import Listfrom pydantic import BaseModelreader = WikipediaReader()tool = OnDemandLoaderTool.from_defaults(reader,name="Wikipedia Tool",description="A tool for loading and querying articles from Wikipedia",
)# run only the llama_Index Tool by itself
tool(["Berlin"], query_str="What's the arts and culture scene in Berlin?")# run tool from LangChain Agent
lc_tool = tool.to_langchain_structured_tool(verbose=True)
lc_tool.run(tool_input={"pages": ["Berlin"], "query_str": "What's the arts and culture scene in Berlin?"})

1.3 引入 langchain.tools 中自带 openai functions

from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessagemodel = ChatOpenAI(model="gpt-3.5-turbo-0613")from langchain.tools import MoveFileTool, format_tool_to_openai_functiontools = [MoveFileTool()]
functions = [format_tool_to_openai_function(t) for t in tools]message = model.predict_messages([HumanMessage(content="move file foo to bar")], functions=functions
)
print(message)
print(message.additional_kwargs["function_call"])

file management


https://python.langchain.com/docs/modules/agents/tools/tools_as_openai_functions

1.4 tools 中再次包装 chains


class CalculatorInput(pydantic.BaseModel):question: str = pydantic.Field()llm_math_chain = LLMMathChain.from_llm(llm=llm, verbose=True)class PrimeInput(pydantic.BaseModel):n: int = pydantic.Field()def get_prime(n: int, primes: dict = primes) -> str:return str(primes.get(int(n)))async def aget_prime(n: int, primes: dict = primes) -> str:return str(primes.get(int(n)))class CalculatorInput(pydantic.BaseModel):question: str = pydantic.Field()tools = [Tool(name="GetPrime",func=get_prime,description="A tool that returns the `n`th prime number",args_schema=PrimeInput,coroutine=aget_prime,),Tool.from_function(func=llm_math_chain.run,name="Calculator",description="Useful for when you need to compute mathematical expressions",args_schema=CalculatorInput,coroutine=llm_math_chain.arun,),
]
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)

1.5 tool 与 vectorstores 结合

利用 embeddings 将数据存入向量数据库,然后进行检索。


from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.text_splitter import CharacterTextSplitter
from langchain.llms import OpenAI
from langchain.chains import RetrievalQAllm = OpenAI(temperature=0)from pathlib import Path
from langchain.document_loaders import TextLoaderdoc_path = "E:\DEVELOP\LLM_Demo\examples\state_of_the_union.txt"loader = TextLoader(doc_path)
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(documents)embeddings = OpenAIEmbeddings()
docsearch = Chroma.from_documents(texts, embeddings, collection_name="state-of-union")state_of_union = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=docsearch.as_retriever()
)
###
from langchain.document_loaders import WebBaseLoader
loader = WebBaseLoader("https://beta.ruff.rs/docs/faq/")docs = loader.load()
ruff_texts = text_splitter.split_documents(docs)
ruff_db = Chroma.from_documents(ruff_texts, embeddings, collection_name="ruff")
ruff = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=ruff_db.as_retriever()
)# Import things that are needed generically
from langchain.agents import initialize_agent, Tool
from langchain.agents import AgentType
from langchain.tools import BaseTool
from langchain.llms import OpenAI
from langchain import LLMMathChain, SerpAPIWrappertools = [Tool(name="State of Union QA System",func=state_of_union.run,description="useful for when you need to answer questions about the most recent state of the union address. Input should be a fully formed question.",),Tool(name="Ruff QA System",func=ruff.run,description="useful for when you need to answer questions about ruff (a python linter). Input should be a fully formed question.",),
]# Construct the agent. We will use the default agent type here.
# See documentation for a full list of options.
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)res = agent.run("What did biden say about ketanji brown jackson in the state of the union address?"
)print(res)

1.6 调用浏览器工具库

如果已有库工具,可以直接将相关的工具作为 tools。


from langchain.agents import AgentType
from langchain.chat_models import ChatOpenAI
from langchain.agents import initialize_agentfrom langchain.agents.agent_toolkits import PlayWrightBrowserToolkit
from langchain.tools.playwright.utils import (create_async_playwright_browser,create_sync_playwright_browser,  # A synchronous browser is available, though it isn't compatible with jupyter.
)async_browser = create_async_playwright_browser()
browser_toolkit = PlayWrightBrowserToolkit.from_browser(async_browser=async_browser)
tools = browser_toolkit.get_tools()llm = ChatOpenAI(temperature=0)  # Also works well with Anthropic models
agent_chain = initialize_agent(tools, llm, agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,verbose=True)response1 = agent_chain.arun(input="Hi I'm Erica.")
print(response1)

1.7 sqlite 数据库加上 chain,整体作为 tool 工具


from langchain import LLMMathChain, OpenAI, SerpAPIWrapper, SQLDatabase, SQLDatabaseChain
from langchain.agents import initialize_agent, Tool
from langchain.agents import AgentTypellm = OpenAI(temperature=0)search = SerpAPIWrapper()
llm_math_chain = LLMMathChain(llm=llm, verbose=True)db = SQLDatabase.from_uri("sqlite:///../../../../../notebooks/Chinook.db")
db_chain = SQLDatabaseChain.from_llm(llm, db, verbose=True)tools = [Tool(name="Search",func=search.run,description="useful for when you need to answer questions about current events. You should ask targeted questions"),Tool(name="Calculator",func=llm_math_chain.run,description="useful for when you need to answer questions about math"),Tool(name="FooBar DB",func=db_chain.run,description="useful for when you need to answer questions about FooBar. Input should be in the form of a question containing full context")
]mrkl = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True) 

1.8 StructuredTool dataclass 进行接口访问

To dynamically generate a structured tool from a given function, the fastest way to get started is with

import requests
from langchain.tools import StructuredTooldef post_message(url: str, body: dict, parameters: Optional[dict] = None) -> str:"""Sends a POST request to the given url with the given body and parameters."""result = requests.post(url, json=body, params=parameters)return f"Status: {result.status_code} - {result.text}"tool = StructuredTool.from_function(post_message)

1.9 decorator 作为 tool

import requests
from langchain.tools import tool@tool
def post_message(url: str, body: dict, parameters: Optional[dict] = None) -> str:"""Sends a POST request to the given url with the given body and parameters."""result = requests.post(url, json=body, params=parameters)return f"Status: {result.status_code} - {result.text}"

https://api.python.langchain.com/en/latest/tools/langchain.tools.base.tool.html

1.10 修改 tool 的属性

tools = load_tools(["serpapi", "llm-math"], llm=llm)tools[0].name = "Google Search"

1.11 Defining the priorities among Tools

对所有包装的工具进行优先级定义。
When you made a Custom tool, you may want the Agent to use the custom tool more than normal tools.
For example, you made a custom tool, which gets information on music from your database. When a user wants information on songs, You want the Agent to use the custom tool more than the normal Search tool. But the Agent might prioritize a normal Search tool.
This can be accomplished by adding a statement such as Use this more than the normal search if the question is about Music, like 'who is the singer of yesterday?' or 'what is the most popular song in 2022?' to the description.
https://python.langchain.com/docs/modules/agents/tools/custom_tools

参考资料:
Introduction | 🦜️🔗 Langchain

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/178663.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

codemirror怎么高亮指定文本

先上图 ![在这里插入图片描述](https://img-blog.csdnimg.cn/c070cde11a314c45a859ccb0ca7f41c7.png 产品经理的需求是编辑框中用了占位符的话&#xff0c;占位符中的变量高亮&#xff0c;简单吧&#xff01;还有一个附加要求&#xff0c;必须是外部定义的变量&#xff0c;不…

多媒体播放器Infuse mac中文版软件特点

Infuse mac是一款多媒体播放器应用&#xff0c;它支持播放多种格式的视频文件、音频文件和图片文件&#xff0c;并且可以通过AIrPlay将媒体内容投放到其他设备上。Infuse还支持在线视频流媒体播放和本地网络共享&#xff0c;用户可以通过它来访问家庭网络上的媒体文件。 Infuse…

upload-labs12-21关

第十二关 提示及源码 $is_upload false; $msg null; if(isset($_POST[submit])){$ext_arr array(jpg,png,gif);$file_ext substr($_FILES[upload_file][name],strrpos($_FILES[upload_file][name],".")1);if(in_array($file_ext,$ext_arr)){$temp_file $_FILES…

计算机网络五层协议的体系结构

计算机网络中两个端系统之间的通信太复杂&#xff0c;因此把需要问题分而治之&#xff0c;通过把一次通信过程中涉及的所有问题分层归类来进行研究和处理 体系结构是抽象的&#xff0c;实现是真正在运行的软件和硬件 1.实体、协议、服务和服务访问点 协议必须把所有不利条件和…

c++基于CImage实现图片格式转换完整源代码

最近遇到项目需要&#xff0c;对图片进行格式转换&#xff0c;抱着怎么简单怎么做的想法&#xff0c;于是进行了验证&#xff0c;代码参考自网络&#xff0c;进行了简单的修改。 我这里提供完整的代码。 直接上代码&#xff1a; 头文件&#xff1a; #pragma once#include &l…

LCD1602命令代码整合

本文为博主 日月同辉&#xff0c;与我共生&#xff0c;csdn原创首发。希望看完后能对你有所帮助&#xff0c;不足之处请指正&#xff01;一起交流学习&#xff0c;共同进步&#xff01; > 发布人&#xff1a;日月同辉,与我共生_单片机-CSDN博客 > 欢迎你为独创博主日月同…

使用Kohya_ss训练Stable Diffusion Lora

Stable Diffusion模型微调方法 Stable Diffusion主要有 4 种方式&#xff1a;Dreambooth, LoRA, Textual Inversion, Hypernetworks。 Textual Inversion &#xff08;也称为 Embedding&#xff09;&#xff0c;它实际上并没有修改原始的 Diffusion 模型&#xff0c; 而是通过…

day18_多线程

今日内容 零、 复习昨日 一、作业 二、线程安全的集合 三、死锁 四、线程通信 五、线程池 零、 复习昨日 见晨考 一、线程安全[重点] 1.0 线程不安全 当前线程的数据被其他线程修改 1.1 线程安全 临界资源&#xff1a;共享资源(同⼀个对象)&#xff0c;一次只可以有一个线程操…

数字化时代,VR虚拟展厅为企业带来全新商机

临近年关&#xff0c;各个行业都想在年关将至之时冲一波销量&#xff0c;各种婚博会、家博会、车展会多不胜数。但是线下展会终归是场地有限&#xff0c;因此为了扩大受众范围&#xff0c;同时节约一定宣传成本&#xff0c;实现全球范围的展示和推广&#xff0c;不少企业都会选…

python基础练习题库实验八

文章目录 前言题目1代码 题目2代码 题目3代码 总结 前言 &#x1f388;关于python小题库的这模块我已经两年半左右没有更新了&#xff0c;主要是在实习跟考研&#xff0c;目前已经上岸武汉某211计算机&#xff0c;目前重新学习这门课程&#xff0c;也做了一些新的题目 &#x…

【星海出品】SDN neutron (五) openvswitch

1、ovs-vswitchd组件是交换机的主要模块&#xff0c;运行在用户态&#xff0c;其主要负责基本的转发逻辑、地址学习、外部物理端口绑定等。还可以运用OVS自带的ovs-ofctl工具采用openflow协议对交换机进行远程配置和管理。 2、ovsdb-server组件是存储OVS的网桥等配置、日志以及…

Flume(一)【Flume 概述】

前言 今天实在不知道学点什么好了&#xff0c;早上学了3个多小时的 Flink &#xff0c;整天只学一门技术是很容易丧失兴趣的。那就学点新的东西 Flume&#xff0c;虽然 Kafka 还没学完&#xff0c;但是大数据生态圈的基础组件也基本就剩这倆了。 Flume 概述 生产环境中的数据一…