赞
踩
第一个案例:
import os
os.environ["OPENAI_API_KEY"] = '你的api key'
from langchain.llms import OpenAI
llm = OpenAI(model_name="text-davinci-003",max_tokens=1024)
llm("怎么评价人工智能")
接下来,我们就来搞点有意思的。我们来让我们的 OpenAI api 联网搜索,并返回答案给我们。
这里我们需要借助 Serpapi 来进行实现,Serpapi 提供了 google 搜索的 api 接口。
首先需要我们到 Serpapi 官网上注册一个用户,https://serpapi.com/ 并复制他给我们生成 api key。
然后我们需要像上面的 openai api key 一样设置到环境变量里面去。
import os os.environ["OPENAI_API_KEY"] = '你的api key' os.environ["SERPAPI_API_KEY"] = '你的api key' from langchain.agents import load_tools from langchain.agents import initialize_agent from langchain.llms import OpenAI from langchain.agents import AgentType # 加载 OpenAI 模型 llm = OpenAI(temperature=0,max_tokens=2048) # 加载 serpapi 工具 tools = load_tools(["serpapi"]) # 如果搜索完想再计算一下可以这么写 # tools = load_tools(['serpapi', 'llm-math'], llm=llm) # 如果搜索完想再让他再用python的print做点简单的计算,可以这样写 # tools=load_tools(["serpapi","python_repl"]) # 工具加载后都需要初始化,verbose 参数为 True,会打印全部的执行详情 agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True) # 运行 agent agent.run("What's the date today? What great events have taken place today in history?")
假如我们想要用 openai api 对一个段文本进行总结,我们通常的做法就是直接发给 api 让他总结。但是如果文本超过了 api 最大的 token 限制就会报错。
这时,我们一般会进行对文章进行分段,比如通过 tiktoken 计算并分割,然后将各段发送给 api 进行总结,最后将各段的总结再进行一个全部的总结。
如果,你用是 LangChain,他很好的帮我们处理了这个过程,使得我们编写代码变的非常简单
from langchain.document_loaders import UnstructuredFileLoader from langchain.chains.summarize import load_summarize_chain from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain import OpenAI # 导入文本 loader = UnstructuredFileLoader("/content/sample_data/data/lg_test.txt") # 将文本转成 Document 对象 document = loader.load() print(f'documents:{len(document)}') # 初始化文本分割器 text_splitter = RecursiveCharacterTextSplitter( chunk_size = 500, chunk_overlap = 0 ) #文本分割器可以参考这个文档:https://python.langchain.com/en/latest/modules/indexes/text_splitters.html # 切分文本 split_documents = text_splitter.split_documents(document) print(f'documents:{len(split_documents)}') # 加载 llm 模型 llm = OpenAI(model_name="text-davinci-003", max_tokens=1500) # 创建总结链 chain = load_summarize_chain(llm, chain_type="refine", verbose=True) # 执行总结链,(为了快速演示,只总结前5段) chain.run(split_documents[:5])
最终输出了对前 5 个 document 的总结。
这个是指切割后的每个 document 里包含几个上一个 document 结尾的内容,主要作用是为了增加每个 document 的上下文关联。比如,chunk_overlap=0时,
第一个 document 为 aaaaaa,第二个为 bbbbbb;当 chunk_overlap=2 时,第一个 document 为 aaaaaa,第二个为 aabbbbbb。
不过,这个也不是绝对的,要看所使用的那个文本分割模型内部的具体算法。
from langchain.embeddings.openai import OpenAIEmbeddings from langchain.vectorstores import Chroma from langchain.text_splitter import CharacterTextSplitter from langchain import OpenAI from langchain.document_loaders import DirectoryLoader from langchain.chains import RetrievalQA # 加载文件夹中的所有txt类型的文件 loader = DirectoryLoader('/content/sample_data/data/', glob='**/*.txt') # 将数据转成 document 对象,每个文件会作为一个 document documents = loader.load() # 初始化加载器 text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=0) # 切割加载的 document split_docs = text_splitter.split_documents(documents) # 初始化 openai 的 embeddings 对象 embeddings = OpenAIEmbeddings() # 将 document 通过 openai 的 embeddings 对象计算 embedding # 向量信息并临时存入 Chroma 向量数据库,用于后续匹配查询 docsearch = Chroma.from_documents(split_docs, embeddings) # 创建问答对象 qa = RetrievalQA.from_chain_type( llm=OpenAI(), chain_type="stuff", retriever=docsearch.as_retriever(), return_source_documents=True ) # 进行问答 result = qa({"query": "科大讯飞今年第一季度收入是多少?"}) print(result)
答:此时使用了stuff,因为这次不是总结,是总结式回答,因此可以使用,精确度更高
因为 LangChain 支持的数据库有很多,所以这里就介绍两个用的比较多的,更多的可以参看文档:https://python.langchain.com/en/latest/modules/indexes/vectorstores/getting_started.html
from langchain.vectorstores import Chroma from langchain.document_loaders import DirectoryLoader from langchain.embeddings.openai import OpenAIEmbeddings # 加载文件夹中的所有txt类型的文件 loader = DirectoryLoader('/content/sample_data/data/', glob='**/*.txt') # 将数据转成 document 对象,每个文件会作为一个 document documents = loader.load() embeddings = OpenAIEmbeddings() # 持久化数据 # docsearch = Chroma.from_documents(split_docs, embeddings) 跟之前不同 主要是加了一个持久化目录进行持久化 docsearch = Chroma.from_documents(documents, embeddings, persist_directory="D:/vector_store") docsearch.persist() # 加载数据 docsearch = Chroma(persist_directory="D:/vector_store", embedding_function=embeddings)
from langchain.text_splitter import CharacterTextSplitter from langchain.document_loaders import DirectoryLoader from langchain.vectorstores import Chroma, Pinecone from langchain.embeddings.openai import OpenAIEmbeddings from langchain.llms import OpenAI from langchain.chains.question_answering import load_qa_chain import pinecone # 初始化 pinecone pinecone.init( api_key="你的api key", environment="你的Environment" ) loader = DirectoryLoader('/content/sample_data/data/', glob='**/*.txt') # 将数据转成 document 对象,每个文件会作为一个 document documents = loader.load() # 初始化加载器 text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=0) # 切割加载的 document split_docs = text_splitter.split_documents(documents) index_name="liaokong-test" # 持久化数据 # docsearch = Pinecone.from_texts([t.page_content for t in split_docs], embeddings, index_name=index_name) # 加载数据 docsearch = Pinecone.from_existing_index(index_name,embeddings) query = "科大讯飞今年第一季度收入是多少?" docs = docsearch.similarity_search(query, include_metadata=True) llm = OpenAI(temperature=0) chain = load_qa_chain(llm, chain_type="stuff", verbose=True) chain.run(input_documents=docs, question=query)
import os from langchain.document_loaders import YoutubeLoader from langchain.embeddings.openai import OpenAIEmbeddings from langchain.vectorstores import Chroma from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.chains import ChatVectorDBChain, ConversationalRetrievalChain from langchain.chat_models import ChatOpenAI from langchain.prompts.chat import ( ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate ) # 加载 youtube 频道 loader = YoutubeLoader.from_youtube_url('https://www.youtube.com/watch?v=Dj60HHy-Kqk') # 将数据转成 document documents = loader.load() # 初始化文本分割器 text_splitter = RecursiveCharacterTextSplitter( chunk_size=1000, chunk_overlap=20 ) # 分割 youtube documents documents = text_splitter.split_documents(documents) # 初始化 openai embeddings embeddings = OpenAIEmbeddings() # 将数据存入临时向量存储 vector_store = Chroma.from_documents(documents, embeddings) # 通过向量存储初始化检索器 retriever = vector_store.as_retriever() system_template = """ Use the following context to answer the user's question. If you don't know the answer, say you don't, don't try to make it up. And answer in Chinese. ----------- {question} ----------- {chat_history} """ # 构建初始 messages 列表,这里可以理解为是 openai 传入的 messages 参数 messages = [ SystemMessagePromptTemplate.from_template(system_template), HumanMessagePromptTemplate.from_template('{question}') ] # 初始化 prompt 对象 prompt = ChatPromptTemplate.from_messages(messages) # 初始化问答链 qa = ConversationalRetrievalChain.from_llm(ChatOpenAI(temperature=0.1,max_tokens=2048),retriever,condense_question_prompt=prompt) chat_history = [] while True: question = input('问题:') # 开始发送问题 chat_history 为必须参数,用于存储对话历史 result = qa({'question': question, 'chat_history': chat_history}) chat_history.append((question, result['answer'])) print(result['answer'])
from langchain.callbacks.base import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
chat = ChatOpenAI(streaming=True, callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]), verbose=True, temperature=0)
resp = chat(chat_prompt_with_values.to_messages())
from langchain.llms import OpenAI from langchain.chains import LLMChain from langchain.prompts import PromptTemplate from langchain.chains import SimpleSequentialChain # location 链 llm = OpenAI(temperature=1) template = """Your job is to come up with a classic dish from the area that the users suggests. % USER LOCATION {user_location} YOUR RESPONSE: """ prompt_template = PromptTemplate(input_variables=["user_location"], template=template) location_chain = LLMChain(llm=llm, prompt=prompt_template) # meal 链 template = """Given a meal, give a short and simple recipe on how to make that dish at home. % MEAL {user_meal} YOUR RESPONSE: """ prompt_template = PromptTemplate(input_variables=["user_meal"], template=template) meal_chain = LLMChain(llm=llm, prompt=prompt_template) # 通过 SimpleSequentialChain 串联起来,第一个答案会被替换第二个中的user_meal,然后再进行询问 overall_chain = SimpleSequentialChain(chains=[location_chain, meal_chain], verbose=True) review = overall_chain.run("Rome")
有时候我们希望输出的内容不是文本,而是像 json 那样结构化的数据
from langchain.output_parsers import StructuredOutputParser, ResponseSchema from langchain.prompts import PromptTemplate from langchain.llms import OpenAI llm = OpenAI(model_name="text-davinci-003") # 告诉他我们生成的内容需要哪些字段,每个字段类型式啥 response_schemas = [ ResponseSchema(name="bad_string", description="This a poorly formatted user input string"), ResponseSchema(name="good_string", description="This is your response, a reformatted response") ] # 初始化解析器 output_parser = StructuredOutputParser.from_response_schemas(response_schemas) # 生成的格式提示符 # { # "bad_string": string // This a poorly formatted user input string # "good_string": string // This is your response, a reformatted response #} format_instructions = output_parser.get_format_instructions() template = """ You will be given a poorly formatted string from a user. Reformat it and make sure all the words are spelled correctly {format_instructions} % USER INPUT: {user_input} YOUR RESPONSE: """ # 将我们的格式描述嵌入到 prompt 中去,告诉 llm 我们需要他输出什么样格式的内容 prompt = PromptTemplate( input_variables=["user_input"], partial_variables={"format_instructions": format_instructions}, template=template ) promptValue = prompt.format(user_input="welcom to califonya!") llm_output = llm(promptValue) # 使用解析器进行解析生成的内容 output_parser.parse(llm_output)
有些时候我们需要爬取一些结构性比较强的网页,并且需要将网页中的信息以JSON的方式返回回来。
我们就可以使用 LLMRequestsChain 类去实现,具体可以参考下面代码
为了方便理解,我在例子中直接使用了Prompt的方法去格式化输出结果,而没用使用上个案例中用到的 StructuredOutputParser去格式化,也算是提供了另外一种格式化的思路
from langchain.prompts import PromptTemplate from langchain.llms import OpenAI from langchain.chains import LLMRequestsChain, LLMChain llm = OpenAI(model_name="gpt-3.5-turbo", temperature=0) template = """在 >>> 和 <<< 之间是网页的返回的HTML内容。 网页是新浪财经A股上市公司的公司简介。 请抽取参数请求的信息。 >>> {requests_result} <<< 请使用如下的JSON格式返回数据 {{ "company_name":"a", "company_english_name":"b", "issue_price":"c", "date_of_establishment":"d", "registered_capital":"e", "office_address":"f", "Company_profile":"g" }} Extracted:""" prompt = PromptTemplate( input_variables=["requests_result"], template=template ) chain = LLMRequestsChain(llm_chain=LLMChain(llm=llm, prompt=prompt)) inputs = { "url": "https://vip.stock.finance.sina.com.cn/corp/go.php/vCI_CorpInfo/stockid/600519.phtml" } response = chain(inputs) print(response['output'])
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, SerpAPIWrapper llm = OpenAI(temperature=0) # 初始化搜索链和计算链 search = SerpAPIWrapper() llm_math_chain = LLMMathChain(llm=llm, verbose=True) # 创建一个功能列表,指明这个 agent 里面都有哪些可用工具,agent 执行过程可以看必知概念里的 Agent 那张图 tools = [ Tool( name = "Search", func=search.run, description="useful for when you need to answer questions about current events" ), Tool( name="Calculator", func=llm_math_chain.run, description="useful for when you need to answer questions about math" ) ] # 初始化 agent agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True) # 执行 agent agent.run("Who is Leo DiCaprio's girlfriend? What is her current age raised to the 0.43 power?")
自定义工具里面有个比较有意思的地方,使用哪个工具的权重是靠 工具中描述内容 来实现的,和我们之前编程靠数值来控制权重完全不同。
比如 Calculator 在描述里面写到,如果你问关于数学的问题就用他这个工具。我们就可以在上面的执行过程中看到,他在我们请求的 prompt 中数学的部分,就选用了Calculator 这个工具进行计算。
上一个例子我们使用的是通过自定义一个列表来存储对话的方式来保存历史的。
当然,你也可以使用自带的 memory 对象来实现这一点。
from langchain.memory import ChatMessageHistory
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI(temperature=0)
# 初始化 MessageHistory 对象
history = ChatMessageHistory()
# 给 MessageHistory 对象添加对话内容
history.add_ai_message("你好!")
history.add_user_message("中国的首都是哪里?")
# 执行对话
ai_response = chat(history.messages)
print(ai_response)
转载于:
https://liaokong.gitbook.io/llm-kai-fa-jiao-cheng/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。