LangChain for LLM Application Development

1.Models,Prompts and Parsers

Model(模型):底层支持的大部分语言模型
Prompts(提示词):为模型创建输入的一种方式
Parsers(解析器):在模型输出的基础上进行解析,以结构化的方式呈现出来,方便后续处理
使用conda安装Langchain的指令见:Langchain官网


2.关于使用Prompt Templates in LangChain

有助于重复使用优秀的prompt,只需要更改其中部分核心的内容,类似于函数接口,将函数实现抽象出来,仅需要提供参数即可使用;

from langchain.chat_models import ChatOpenAI
#这一步是初始化一个聊天模型,传入API的KEY
#需要注意的是可能需要通过参数名指定openai_api_key的值
chat = ChatOpenAI(openai_api_key = os.getenv("CHATGPT_API_KEY"),temperature = 0)
#演示用的Prompt Template
template_string = """Translate the text \
that is delimited by triple backticks \
into a style that is {style}. \
text: ```{text}```
"""
#导入响应的类
from langchain.prompts import ChatPromptTemplate
#根据提供的字符串生成对应的Prompt Template,类似于函数的定义和初始化
prompt_template = ChatPromptTemplate.from_template(template_string)
#查看生成的Prompt Template
prompt_template.messages[0].prompt
#查看生成模板的所需输入参数
prompt_template.messages[0].prompt.input_variables

#模板的两个参数
customer_style = """American English \
in a calm and respectful tone
"""
customer_email = """
Arrr, I be fuming that me blender lid \
flew off and splattered me kitchen walls \
with smoothie! And to make matters worse, \
the warranty don't cover the cost of \
cleaning up me kitchen. I need yer help \
right now, matey!
"""
#使用模板将两个参数传递进去,类似调用函数过程
customer_messages = prompt_template.format_messages(
                    style=customer_style,
                    text=customer_email)
#查看参数是否成功按照模板放入customer_messages中
print(customer_messages[0])
#使用之前初始化的模型变量chat向LLM传递消息,并用customer_response接收返回结果
customer_response = chat(customer_messages)
#打印模型响应内容
print(customer_response.content)

3.关于使用Parser(解释器)来格式化output

首先导入LangChain响应的函数

from langchain.output_parsers import ResponseSchema
from langchain.output_parsers import StructuredOutputParser

其次制定所需要的格式化shcema

gift_schema = ResponseSchema(name="gift",
                             description="Was the item purchased\
                             as a gift for someone else? \
                             Answer True if yes,\
                             False if not or unknown.")
delivery_days_schema = ResponseSchema(name="delivery_days",
                                      description="How many days\
                                      did it take for the product\
                                      to arrive? If this \
                                      information is not found,\
                                      output -1.")
price_value_schema = ResponseSchema(name="price_value",
                                    description="Extract any\
                                    sentences about the value or \
                                    price, and output them as a \
                                    comma separated Python list.")

#制定好回应的样式,list类型
response_schemas = [gift_schema, 
                    delivery_days_schema,
                    price_value_schema]

将制定好的样式生成输出解释器

output_parser = StructuredOutputParser.from_response_schemas(response_schemas)

再根据输出解释器生成响应的prompt提示词,以便后续放入message中交由LLM执行

format_instructions = output_parser.get_format_instructions()

将生成的解释器提示词放入Prompt中

review_template_2 = """\
For the following text, extract the following information:

gift: Was the item purchased as a gift for someone else? \
Answer True if yes, False if not or unknown.

delivery_days: How many days did it take for the product\
to arrive? If this information is not found, output -1.

price_value: Extract any sentences about the value or price,\
and output them as a comma separated Python list.

text: {text}

{format_instructions}
"""

根据review_template_2生成对应的prompt模板,并向模版中传入所需的参数

prompt = ChatPromptTemplate.from_template(review_template_2)

messages = prompt.format_messages(text=customer_review, 
                                format_instructions=format_instructions)

将提示词交由LLM分析处理

response = chat(messages)

查看response中的返回内容

print(response.content)

使用解释器来将返回内容格式化输出并存储在output_dict中,显示为dictionary类型

output_dict = output_parser.parse(response.content)
print(type(output_dict))

4. Memory:使模型记住上下文,即之前的对话

4.1 ConversationBufferMemory

首先引入三个用到的LangChain的函数

from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory

分别创建并初始化所需要的语言模型和memory,并将两者作为参数传入,以完成ConversationChain的初始化
其中Verbose参数控制的是:

是否显示ConversationChain中的详细信息,在后续打印信息中可以看出来

llm = ChatOpenAI(openai_api_key = openai.api_key,temperature = 0)
memory = ConversationBufferMemory()
conversation = ConversationChain(
    llm = llm,
    memory = memory,
    verbose = True)

经过如下操作可以看出ConversationChain的详细信息
同时也会发现Chain很好地自动完成了上下文的链接,以帮助LLM记住上下文

conversation.predict(input = "Hi,I'm Marcus")
conversation.predict(input = "Can you tell me where is the capital of Chain?")
conversation.predict(input = "Do you still remember my name?")

如下两行代码可以查看当前memory中存储的对话

print(memory.buffer)
#此处的双大括号代表一个空字典,为必要参数
#该函数还有很多别的强大功能,先按下不表
memory.load_memory_variables({})

函数save_context可以通过如下函数完成对memory的增加内容操作

memory.save_context({"input":"Hi"},{"output":"What's up"})

LLM的每次对话都是独立的API调用,并不包括上下文的链接,看起来LLM好像具备“记忆”能力,是因为有代码将这一功能封装实现好了;
以至于,每次调用API时,都是传递之前记录的完整的对话内容;
但由于随着对话的增加,每次调用API所需要传递的数据量增大,token数量也将增大,为降低成本LangChain有其他灵活便捷的存储方式

4.2 ConversationBufferWindowMemory

使用对话次数来限制记忆的篇幅
创建时代码如下:
其中参数k限制了回话的篇幅,如示例中的k = 1表示只会存储双方上一次的对话

from langchain.memory import ConversationBufferWindowMemory
#创建Memory
memory = ConversationBufferWindowMemory(k = 1)
#创建模型
llm = ChatOpenAI(openai_api_key = openai.api_key,temperature = 0)
#创建会话
conversation = ConversationChain(
    llm = llm,
    memory = memory,
    verbose = True)

4.3 ConversationTokenBufferMemory

使用token限制记忆的篇幅
代码如下:
在ConversationTokenBufferMemory函数中,需要两个参数

  • 一个是LLM模型,因为不同的LLM有不同的Token计数方式
  • 另一个是限制的Token数量
from langchain.memory import ConversationTokenBufferMemory
memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=30)
memory.save_context({"input": "AI is what?!"},
                    {"output": "Amazing!"})
memory.save_context({"input": "Backpropagation is what?"},
                    {"output": "Beautiful!"})
memory.save_context({"input": "Chatbots are what?"}, 
                    {"output": "Charming!"})

通过改变Token数量可以通过下面的代码查看memory中存储的对话信息:

memory.load_memory_variables({})

4.4 ConversationSummaryBufferMemory

通过LLM将过去的对话进行总结,再将其装载入memory中节省篇幅
对于在token限制范围内的信息会显式存储,而在这之外的则会被总结存储
类似于TokenMemory,在创建SummaryMemory时需要提供LLM和max_token_limit两个参数

代码如下:

from langchain.memory import ConversationTokenBufferMemory
# create a long string
schedule = "There is a meeting at 8am with your product team. \
You will need your powerpoint presentation prepared. \
9am-12pm have time to work on your LangChain \
project which will go quickly because Langchain is such a powerful tool. \
At Noon, lunch at the italian resturant with a customer who is driving \
from over an hour away to meet you to understand the latest in AI. \
Be sure to bring your laptop to show the latest LLM demo."
#创建SummaryBufferMemory
memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100)
memory.save_context({"input": "Hello"}, {"output": "What's up"})
memory.save_context({"input": "Not much, just hanging"},
                    {"output": "Cool"})
memory.save_context({"input": "What is on the schedule today?"}, 
                    {"output": f"{schedule}"})

为了验证并理解其功能
测试代码如下:

memory.load_memory_variables({})
conversation = ConversationChain(
    llm = llm,
    memory = memory,
    verbose = True)
conversation.predict(input = "What is a good demo?")
memory.load_memory_variables({})

5. Chains

将一个LLM和提示词prompt连接在一起,通过多个这样的基础构建的块可以实现对数据的一系列操作

5.1 LLMChain

首先,导入所需要的一系列函数:

from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.chains import LLMChain

初始化所需要使用的模型:

llm = ChatOpenAI(temperature=0.9)

创建提示词模板:

prompt = ChatPromptTemplate.from_template(
    "What is the best name to describe \
    a company that makes {product}?"
)

使用LLMChain链接模型与提示词模板:

chain = LLMChain(llm=llm, prompt=prompt)

提供提示词模板中所需要的参数并将其传入运行:

product = "Queen Size Sheet Set"
chain.run(product)

5.2 SimpleSequentialChain

依次运行一系列的Chain,适用于子链仅有一个输入和一个输出的情况
首先导入响应函数:

from langchain.chains import SimpleSequentialChain

初始化LLM以及一个提示词模板,并链接起来:
提示词用于根据一个产品名称给出公司名

llm = ChatOpenAI(temperature=0.9)

# prompt template 1
first_prompt = ChatPromptTemplate.from_template(
    "What is the best name to describe \
    a company that makes {product}?"
)

# Chain 1
chain_one = LLMChain(llm=llm, prompt=first_prompt)

创建第二个提示词模板,并与LLM链接:
提示词用于根据一个公司名给出相应的公司描述


# prompt template 2
second_prompt = ChatPromptTemplate.from_template(
    "Write a 20 words description for the following \
    company:{company_name}"
)
# chain 2
chain_two = LLMChain(llm=llm, prompt=second_prompt)

将两个LLMChain装入SimpleSequentialChain,并按照顺序执行:

overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two],
                                             verbose=True
                                            )
overall_simple_chain.run(product)

5.3 SequentialChain

适用于在子链有多个输入或多个输出时
首先导入所需要的函数:

from langchain.chains import SequentialChain

创建第一个LLMChain,并指定output_key:

llm = ChatOpenAI(temperature=0.9)

# prompt template 1: translate to english
first_prompt = ChatPromptTemplate.from_template(
    "Translate the following review to english:"
    "\n\n{Review}"
)
# chain 1: input= Review and output= English_Review
chain_one = LLMChain(llm=llm, prompt=first_prompt, 
                     output_key="English_Review"
                    )

创建第二个LLMChain,并指定output_key:

second_prompt = ChatPromptTemplate.from_template(
    "Can you summarize the following review in 1 sentence:"
    "\n\n{English_Review}"
)
# chain 2: input= English_Review and output= summary
chain_two = LLMChain(llm=llm, prompt=second_prompt, 
                     output_key="summary"
                    )

创建第三个LLMChain,并指定output_key:

# prompt template 3: translate to english
third_prompt = ChatPromptTemplate.from_template(
    "What language is the following review:\n\n{Review}"
)
# chain 3: input= Review and output= language
chain_three = LLMChain(llm=llm, prompt=third_prompt,
                       output_key="language"
                      )

创建第四个LLMChain,并指定output_key:

# prompt template 4: follow up message
fourth_prompt = ChatPromptTemplate.from_template(
    "Write a follow up response to the following "
    "summary in the specified language:"
    "\n\nSummary: {summary}\n\nLanguage: {language}"
)
# chain 4: input= summary, language and output= followup_message
chain_four = LLMChain(llm=llm, prompt=fourth_prompt,
                      output_key="followup_message"
                     )

将上述四个LLMChain组合起来,并输入SequentialChain:

# overall_chain: input= Review 
# and output= English_Review,summary, followup_message
overall_chain = SequentialChain(
    chains=[chain_one, chain_two, chain_three, chain_four],
    input_variables=["Review"],
    output_variables=["English_Review", "summary","followup_message"],
    verbose=True
)

最终运行SequentialChain,查看运行效果:

review = df.Review[5]
overall_chain(review)

5.4 RouterChain

处理更为复杂的任务,类似于有分支的情形
首先,将四种学科的template初始化好:

physics_template = """You are a very smart physics professor. \
You are great at answering questions about physics in a concise\
and easy to understand manner. \
When you don't know the answer to a question you admit\
that you don't know.

Here is a question:
{input}"""


math_template = """You are a very good mathematician. \
You are great at answering math questions. \
You are so good because you are able to break down \
hard problems into their component parts, 
answer the component parts, and then put them together\
to answer the broader question.

Here is a question:
{input}"""

history_template = """You are a very good historian. \
You have an excellent knowledge of and understanding of people,\
events and contexts from a range of historical periods. \
You have the ability to think, reflect, debate, discuss and \
evaluate the past. You have a respect for historical evidence\
and the ability to make use of it to support your explanations \
and judgements.

Here is a question:
{input}"""


computerscience_template = """ You are a successful computer scientist.\
You have a passion for creativity, collaboration,\
forward-thinking, confidence, strong problem-solving capabilities,\
understanding of theories and algorithms, and excellent communication \
skills. You are great at answering coding questions. \
You are so good because you know how to solve a problem by \
describing the solution in imperative steps \
that a machine can easily interpret and you know how to \
choose a solution that has a good balance between \
time complexity and space complexity. 

Here is a question:
{input}"""

使用list,将其构成便于处理的数据结构:

prompt_infos = [
    {
        "name": "physics", 
        "description": "Good for answering questions about physics", 
        "prompt_template": physics_template
    },
    {
        "name": "math", 
        "description": "Good for answering math questions", 
        "prompt_template": math_template
    },
    {
        "name": "History", 
        "description": "Good for answering history questions", 
        "prompt_template": history_template
    },
    {
        "name": "computer science", 
        "description": "Good for answering computer science questions", 
        "prompt_template": computerscience_template
    }
]

导入所需要用到的函数:

from langchain.chains.router import MultiPromptChain
from langchain.chains.router.llm_router import LLMRouterChain,RouterOutputParser
from langchain.prompts import PromptTemplate

初始化所需要的LLM:

llm = ChatOpenAI(temperature=0)

创建destination_chains字典,并将上述template与LLM链接起来。装入该字典:

#初始化终点链接字典
destination_chains = {}
for p_info in prompt_infos:
#根据关键字“name”提取学科类别
    name = p_info["name"]
#根据关键字“prompt_template”提取模板
    prompt_template = p_info["prompt_template"]
#根据template生成相应的prompt
    prompt = ChatPromptTemplate.from_template(template=prompt_template)
#链接LLM和prompt
    chain = LLMChain(llm=llm, prompt=prompt)
#并根据关键字“name”将链接装入destination_chains字典
    destination_chains[name] = chain  
    
#将prompt_infos字典中的元素以字符串的形式装入destinations列表
destinations = [f"{p['name']}: {p['description']}" for p in prompt_infos]
#使用"\n"分割destinations的各个元素,使之成为字符串
destinations_str = "\n".join(destinations)

创建一个默认的链接,以适应上述学科均未涉及的情况:

default_prompt = ChatPromptTemplate.from_template("{input}")
default_chain = LLMChain(llm=llm, prompt=default_prompt)

以下为多提示词路由template:

MULTI_PROMPT_ROUTER_TEMPLATE = """Given a raw text input to a \
language model select the model prompt best suited for the input. \
You will be given the names of the available prompts and a \
description of what the prompt is best suited for. \
You may also revise the original input if you think that revising\
it will ultimately lead to a better response from the language model.

<< FORMATTING >>
Return a markdown code snippet with a JSON object formatted to look like:
json
{{{{
    "destination": string \ name of the prompt to use or "DEFAULT"
    "next_inputs": string \ a potentially modified version of the original input
}}}}


REMEMBER: "destination" MUST be one of the candidate prompt \
names specified below OR it can be "DEFAULT" if the input is not\
well suited for any of the candidate prompts.
REMEMBER: "next_inputs" can just be the original input \
if you don't think any modifications are needed.

<< CANDIDATE PROMPTS >>
{destinations}

<< INPUT >>
{{input}}

<< OUTPUT (remember to include the ```json)>>"""

根据上述template生成routechain:

#用destinations_str替换destinations
router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(
    destinations=destinations_str
)
router_prompt = PromptTemplate(
    template=router_template,
    input_variables=["input"],
#Parser将帮助链决定要路由到哪条子链
    output_parser=RouterOutputParser(),
)
#链接LLM与router_prompt
router_chain = LLMRouterChain.from_llm(llm, router_prompt)

最后链接好多提示词链接:

chain = MultiPromptChain(
                         router_chain=router_chain, 
                         destination_chains=destination_chains, 
                         default_chain=default_chain, 
                         verbose=True
                        )

接下来即可使用该chain完成复杂的操作:

chain.run("What is black body radiation?")

6. Question & Answer Over Documents

将语言模型与文档结合起来,但一般的语言模型只能检查几千词,如何处理数据量大的文档;
这就是嵌入(Embedding)库和向量(Vector)库的作用

6.1 嵌入(Embedding)

为文本创建数值表示,数值表示捕获了它所覆盖的文本片段的语义含义,内容相似的文本中会含有相似的向量;
让我们能够在向量空间中比较文本片段;


屏幕截图 2023-08-09 160800.png

这在我们决定将哪些文本传给LLM来回答问题时十分有用;

6.2 向量数据库(Vector Database)

是存储上一部分创建的向量表示的一种方式;
创建该向量数据库的方式,是将来自传入文档的文本片段填充进去;
在面对大文档时,先将其切片成小的文本段,以便将小段的相关文本传给LLM,然后为这些小文本段创建嵌入,再将这些嵌入存入向量数据库;

屏幕截图 2023-08-09 163940.png

在query出现时,先为其创建一个嵌入,后将其向量与向量数据库中的所有向量进行比较,选出最接近的几个向量;
返回选中的向量,然后将其放入提示词传给LLM,以获得最终回答;
屏幕截图 2023-08-09 164813.png

6.3 示例代码

CSDN可参阅的资料
index = VectorstoreIndexCreator函数是一个包装了很多别的逻辑操作的函数,包括创建嵌入,初始化索引,生成检索器

6.3.1 简易版

导入相关的函数:

#用于对文档进行检索
from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI
#文档加载,用于加载将要和模型结合的文档数据
from langchain.document_loaders import CSVLoader
#向量存储器
from langchain.vectorstores import DocArrayInMemorySearch
from IPython.display import display, Markdown

初始化文件路径,并用加载器加载该文件:

file = 'OutdoorClothingCatalog_1000.csv'
loader = CSVLoader(file_path=file)

导入库:

#用于创建一个向量库
from langchain.indexes import VectorstoreIndexCreator

创建一个向量库:

#第一个参数指定了向量库的类型
#第二个loader为作为输入的文档加载器列表
index = VectorstoreIndexCreator(
    vectorstore_cls=DocArrayInMemorySearch
).from_loaders([loader])

创建询问query:

query ="Please list all your shirts with sun protection \
in a table in markdown and summarize each one."

使用向量库index针对询问进行查询:

response = index.query(query)
display(Markdown(response))

6.3.2 详尽版

首先创建一个文档加载器,并加载文档:

loader = CSVLoader(file_path=file)
docs = loader.load()

创建嵌入:

from langchain.embeddings import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()

embeddings将请求转成一个向量,代码如下:

embed = embeddings.embed_query("Hi my name is Harrison")
print(len(embed))
print(embed[:5])

为载入的所有文档创建嵌入,并将其存储在向量数据库中:

#接收文档列表和一个嵌入对象(Embedding Objective),并生成一个向量数据库
db = DocArrayInMemorySearch.from_documents(
    docs, 
    embeddings
)

使用生成的向量数据库来找到与传入查询(query)相似的文本片段:

query = "Please suggest a shirt with sunblocking"
docs = db.similarity_search(query)
len(docs)
docs[0]

利用已有的向量索引即向量数据库来生成相应的检索器:

retriever = db.as_retriever()

创建LLM对象:

llm = ChatOpenAI(temperature = 0.0)

将文档列表连接为一个长字符串,并作为提示词的一部分传给LLM:

qdocs = "".join([docs[i].page_content for i in range(len(docs))])
response = llm.call_as_llm(f"{qdocs} Question: Please list all your \
shirts with sun protection in a table in markdown and summarize each one.") 
display(Markdown(response))

将上述操作组合成一个链,并使用该链:

#该链的作用是先进行检索,后在检索到的文档上进行回答
qa_stuff = RetrievalQA.from_chain_type(
#LLM,用于最后回答文本的生成
    llm=llm, 
#设置Chain的类型
    chain_type="stuff", 
#获取文档的接口,将被用于获取文档并被传递给语言模型
    retriever=retriever, 
    verbose=True
)
query =  "Please list all your shirts with sun protection in a table \
in markdown and summarize each one."
response = qa_stuff.run(query)
display(Markdown(response))

也可以用下列代码实现响应:

response = index.query(query, llm=llm)

创建链时有四种不同的类型

  • stuff:将所有内容放在一个提示词中,交由LLM并获得回复;
  • Map_reduce:接受所有的文本片段,将他们和问题一起交给LLM,得到一个回答,再将这些回答由另一个LLM调用进行汇总;
  • Refine :迭代处理文档,当前回答总是基于上一个文档的回答之上的;
  • Map_rerank:对每个文档都进行一次LLM调用,并要求返回一个分数,选择最高分,但需要你在提示词中定义评分标准;

7.Evaluation:评估应用程序的性能

首先构建一个应用程序,例子为上一节的程序:

from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI
from langchain.document_loaders import CSVLoader
from langchain.indexes import VectorstoreIndexCreator
from langchain.vectorstores import DocArrayInMemorySearch
file = 'OutdoorClothingCatalog_1000.csv'
loader = CSVLoader(file_path=file)
data = loader.load()
index = VectorstoreIndexCreator(
    vectorstore_cls=DocArrayInMemorySearch
).from_loaders([loader])
llm = ChatOpenAI(temperature = 0.0)
qa = RetrievalQA.from_chain_type(
    llm=llm, 
    chain_type="stuff", 
    retriever=index.vectorstore.as_retriever(), 
    verbose=True,
    chain_type_kwargs = {
        "document_separator": "<<<<>>>>>"
    }
)

找一些想对其进行评估的数据点,将会有多个方法实现该目标
我们提出一些我们认为是好示例的数据点
手动方式,自己查看doc并写出QA example:

data[10]
data[11]
examples = [
    {
        "query": "Do the Cozy Comfort Pullover Set\
        have side pockets?",
        "answer": "Yes"
    },
    {
        "query": "What collection is the Ultra-Lofty \
        850 Stretch Down Hooded Jacket from?",
        "answer": "The DownTek collection"
    }
]

使用Chain自动化生成QA的examples,可以节省很多时间:

from langchain.evaluation.qa import QAGenerateChain
example_gen_chain = QAGenerateChain.from_llm(ChatOpenAI())
new_examples = example_gen_chain.apply_and_parse(
    [{"doc": t} for t in data[:5]]
)
new_examples[0]

将手动生成的examples和自动生成的examples结合起来,并使用链运行其中的一个请求:

examples += new_examples
qa.run(examples[0]["query"])

评估环节
手动Evaluate:
“自己评估”
仅仅查看链输出的结果很难进行错误分析,因此需要将debug置为True并再次运行展示详细信息:

import langchain
langchain.debug = True
qa.run(examples[0]["query"])

LLM辅助评估:
调用一个新的LLM构成一个EvalChain(评估链)来对刚刚的LLM生成的内容进行评估

# Turn off the debug mode
langchain.debug = False
predictions = qa.apply(examples)
from langchain.evaluation.qa import QAEvalChain
llm = ChatOpenAI(temperature=0)
eval_chain = QAEvalChain.from_llm(llm)
graded_outputs = eval_chain.evaluate(examples, predictions)
for i, eg in enumerate(examples):
    print(f"Example {i}:")
    print("Question: " + predictions[i]['query'])
    print("Real Answer: " + predictions[i]['answer'])
    print("Predicted Answer: " + predictions[i]['result'])
    print("Predicted Grade: " + graded_outputs[i]['text'])
    print()

8. Agent:LangChain的一个组件

LLM通过用户提供的新的知识和数据,帮助用户回答问题或通过内容进行推理;
例子中的tools有维基百科的api
首先引入需要用到的函数:

from langchain.agents.agent_toolkits import create_python_agent
from langchain.agents import load_tools, initialize_agent
from langchain.agents import AgentType
from langchain.tools.python.tool import PythonREPLTool
from langchain.python import PythonREPL
from langchain.chat_models import ChatOpenAI

创建LLM和需要用到的tools:

llm = ChatOpenAI(temperature=0)
tools = load_tools(["llm-math","wikipedia"], llm=llm)

接着创建一个Agent:

agent= initialize_agent(
    tools, 
    llm, 
#CHAT:表示这是一个优化过后的聊天代理
#REACT:一种提示词技术,旨在从语言模型中获得最佳推理
    agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION,
#当输出格式出错时,将错误文本传回给LLM,要求其自我修正
    handle_parsing_errors=True,
    verbose = True)

询问数学问题:

agent("What is the 25% of 300?")

询问维基百科查询:

question = "Tom M. Mitchell is an American computer scientist \
and the Founders University Professor at Carnegie Mellon University (CMU)\
what book did he write?"
result = agent(question) 

使用语言模型书写代码然后执行:

agent = create_python_agent(
    llm,
#REPL可以视作一个NoteBook,用于执行代码
    tool=PythonREPLTool(),
    verbose=True
)

向agent发布指令请求排序:

customer_list = [["Harrison", "Chase"], 
                 ["Lang", "Chain"],
                 ["Dolly", "Too"],
                 ["Elle", "Elem"], 
                 ["Geoff","Fusion"], 
                 ["Trance","Former"],
                 ["Jen","Ayai"]
                ]
agent.run(f"""Sort these customers by \
last name and then first name \
and print the output: {customer_list}""") 

查看agent详细运行过程:

import langchain
langchain.debug=True
agent.run(f"""Sort these customers by \
last name and then first name \
and print the output: {customer_list}""") 
langchain.debug=False

定义自己的tool,并加入tools中:

#!pip install DateTime
from langchain.agents import tool
from datetime import date
@tool
def time(text: str) -> str:
#一定要对该函数进行文本说明
    """Returns todays date, use this for any \
    questions related to knowing todays date. \
    The input should always be an empty string, \
    and this function will always return todays \
    date - any date mathmatics should occur \
    outside this function."""
    return str(date.today())

agent= initialize_agent(
    tools + [time], 
    llm, 
    agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION,
    handle_parsing_errors=True,
    verbose = True)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352

推荐阅读更多精彩内容