Article Directory
- LangChain Chinese Introductory Tutorial
-
- 1. Introduction
- 2. Must-know concepts
- Three, actual combat
-
- 3.1 Single Q&A
- 3.2 Google search and return answers
- 3.3 Summarizing super long texts
- 3.4 Building a local knowledge base question answering robot
- 3.5 Building a vector index database
- 3.6 Use the GPT3.5 model to build a question-and-answer robot for YouTube channels
- 3.7 Connect thousands of tools with OpenAI
- 4. Small example
- V. Summary
LangChain Chinese Introductory Tutorial
colab address (including all cases in this article) , gitbook (easy to read) , github address
If you want to modify the request root route of OPENAI API to your own proxy address, you can
OPENAI\_API\_BASE
modify it by setting the environment variable " ", refer to the code . Or when initializing OpenAI-related model objects, pass in the "openai_api_base" variable, refer to the code .
1. Introduction
LangChain Official Documentation
1.1 Background
As we all know, OpenAI's API cannot be connected to the Internet, so if you only use your own functions to realize online search and give answers, summarize PDF documents, conduct questions and answers based on a Youtube video, etc., it will definitely not be possible. So, let's introduce a very powerful third-party open source library: LangChain
.
LangChain is a framework for developing applications driven by language models. He mainly has 2 abilities:
- Possibility to connect LLM models (Large-Scale Language Models) with external data sources
- Allows interaction with LLM models
1.2 Basic functions
- Support multiple model interfaces, such as OpenAI, Hugging Face, AzureOpenAI…
- Fake LLM for testing
- Cache support, such as in-mem (memory), SQLite, Redis, SQL
- usage record
- Support stream mode (that is, return word by word, similar to typing effect)
Prompt management, support various custom templates
Has a large number of document loaders, such as Email, Markdown, PDF, Youtube...
Support for indexes
- document splitter
- vectorization
- Docking vector storage and search, such as Chroma, Pinecone, Qdrand
Chains
- LLMChain
- Various Tools Chain
- LangChainHub
2. Must-know concepts
I believe that most of you will be confused after reading the above introduction. Don't worry, the above concepts are not very important at the beginning of learning. After we finish the following examples, you will understand a lot when you come back and read the above content. However, the following concepts must be known.
2.1 Loader loader
As the name implies, this is to load data from the specified source. for example:
- folder
DirectoryLoader
, - Azure Storage
AzureBlobStorageContainerLoader
- CSV file
CSVLoader
- Evernote
EverNoteLoader
- Google Drive
GoogleDriveLoader
- any web page
UnstructuredHTMLLoader
- PDF
PyPDFLoader
- S3
S3DirectoryLoader
/S3FileLoader
、 - Youtube
YoutubeLoader
The above is just a brief list of a few, and the official provides a lot of loaders for you to use.
2.2 Document document
After using loader
the loader to read the data source, the data source needs to be converted into Document
an object before it can be used later.
2.3 Text Spltters text segmentation
As the name suggests, text segmentation is used to segment text. Why do you need to split text? Because every time we send the text as prompt
or openai api
use openai api embedding
the function, there is a character limit.
For example, if we send a 300-page pdf to openai api
him and ask him to make a summary, he will definitely report an error of exceeding the maximum Token. So here we need to use a text splitter to split what we loader
come in Document
.
2.4 Vectorstores vector database
Because the data correlation search is actually a vector operation. Therefore, whether we use the function or directly query through the vector database, we need to vectorize openai api embedding
our loaded data in order to perform vector operation search. Document
Converting to a vector is also very simple. We only need to store the data in the corresponding vector database to complete the vector conversion. The official also provides a lot of vector databases for us to use.
2.5 Chain
We can understand Chain as a task. A Chain is a task, of course, like a chain, multiple chains can be executed one by one.
2.6 Agent agent
We can simply understand that it can dynamically help us select and call chains or existing tools. The execution process can refer to the following picture:
2.7 Embedding
Embedding is used to measure the relevance of text, which is also the key to OpenAI API's ability to build its own knowledge base. Compared with fine-tuning
the biggest advantage is that there is no need for training, and new content can be added in real time, instead of training once after adding new content, and the cost in all aspects is much lower than fine-tuning. For specific comparison and selection, please refer to this video .
Three, actual combat
The following uses the Open AI example to illustrate, and you can also replace it with the LLM model you need according to the needs of your tasks.
3.1 Single Q&A
Before starting, we need to set up our openai key, which can be created in the user management, so I won't go into details here.
import os
os.environ["OPENAI_API_KEY"] = '你的api key'
Then we import and execute
from langchain.llms import OpenAI
llm = OpenAI(model_name="text-davinci-003",max_tokens=1024)
llm("怎么评价人工智能")
At this time, we can see the result he returned to us, how is it, is it very simple?
3.2 Google search and return answers
Next, let's do something interesting. Let's make our OpenAI api search the Internet and return the answer to us.
Here we need to Serpapi
implement with the help of , Serpapi
which provides the api interface of google search. First, we need to register a user on the Serpapi official website , and copy him to generate for us api key
. openai api key
Then we need to set it to the environment variable as above .
serpapi
It seems that it is not very friendly to Chinese, so the prompt for asking questions suggests using English.
import os
os.environ["OPENAI_API_KEY"] = '你的api key'
os.environ["SERPAPI_API_KEY"] = '你的api key'
Then, start writing my code
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?")
We can see that he returned the date correctly (with time difference), and returned today in history.
Both chain and agent objects have verbose
this parameter. This is a very useful parameter. After enabling it, we can see the complete chain execution process. As you can see from the results returned above, he split our problem into several steps, and then got the final answer step by step.
About agent type
the meaning of several options (if you can’t understand it, it will not affect the following learning, and you will understand it naturally if you use it too much):
zero-shot-react-description
:: Determine which tool to use based on the description of the tool and the content of the request (most commonly used)react-docstore
:: Use the ReAct framework to interact with docstore, useSearch
andLookup
tools, the former is used to search, the latter is used to search for terms, for example:Wipipedia
toolsself-ask-with-search
: This agent only uses one tool: Intermediate Answer, which will look for factual answers to questions (referring to non-gpt-generated answers, but existing in the network and text), such asGoogle search API
toolsconversational-react-description
:: An agent designed for session settings, its prompt will be designed to be conversational, and it will still use the ReAct framework to decide which tool to use, and store past session interactions in memory
Python implementation of LLM's ReAct pattern: https://til.simonwillison.net/llms/python-react-pattern
Of course, the official agent has been written ChatGPT Plugins
, what plug-ins can be used in chatgpt in the future, we can also use plug-ins in the api, it is very happy to think about it. However, only plug-ins without authorization can be used at present. We look forward to the official solution to this problem in the future. If you are interested, you can read this document .
Chatgpt can only make money for the official, but Openai API can make money for me
3.3 Summarizing super long texts
If we want to use to openai api
summarize a piece of text, our usual practice is to send it directly to the api for him to summarize. But if the text exceeds the maximum token limit of the api, an error will be reported.
At this time, we usually segment the article, such as by tiktoken
calculating and dividing, and then send each segment to the API for summary, and finally summarize the summary of each segment.
LangChain
It can help us handle this process very well, and the code is very simple.
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
)
# 切分文本
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])
First, we printed the number of documents before and after cutting. We can see that there is only one document before cutting. After cutting, the above document will be cut into 317 documents.
Finally, a summary of the first 5 documents is output.
There are a few parameters to be aware of here:
chunk_overlap
1. The parameters of the text splitter
This means that each document after cutting contains several contents at the end of the previous document. The main function is to increase the context association of each document. For example, chunk_overlap=0
when, the first document is aaaaaa, and the second is bbbbbb; at that chunk_overlap=2
time , the first document is aaaaaa, and the second is aabbbbbb. However, this is not absolute, it depends on the specific algorithm inside the text segmentation model used.
Text splitter reference this document
2. Chain chain_type
parameters
This parameter mainly controls the way to pass the document to the llm model. There are 4 ways in total:
-
stuff
:: This is the most simple and rude, and will pass all documents to the llm model for summary. If there are many documents, it is bound to report an error exceeding the maximum token limit, so this is generally not selected when summarizing the text. -
map_reduce
:: This method will first summarize each document, and finally summarize the results of all documents.
refine
:: In this way, the first document will be summarized first, and then the content summarized in the first document and the second document will be sent to the llm model for summary, and so on. The advantage of this method is that when summarizing the latter document, it will summarize with the previous document, adding context to the document that needs to be summarized, and increasing the coherence of the summarized content.
map_rerank
:: This is generally not used in the summary chain, but in the question and answer chain. It is actually a matching method for searching answers. First you have to give a question, he will calculate a probability score for each document according to the question, and then find the document with the highest score, and convert this document into a part of the prompt of the question (question +document) to the llm model, and finally the llm model returns a specific answer.
3.4 Building a local knowledge base question answering robot
In this example, we will introduce how to read multiple documents from our local to build a knowledge base, and use Openai API to search in the knowledge base and give answers. This is a very useful tutorial, for example, it is very convenient to make a robot that can introduce the company's business, or a robot that introduces a product.
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.text_splitter import CharacterTextSplitter
from langchain import OpenAI,VectorDBQA
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 = VectorDBQA.from_chain_type(llm=OpenAI(), chain_type="stuff", vectorstore=docsearch,return_source_documents=True)
# 进行问答
result = qa({
"query": "科大讯飞今年第一季度收入是多少?"})
print(result)
We can see from the results that he successfully obtained the correct answer from our given data.
3.5 Building a vector index database
One step in our last case is to convert document information into vector information and embeddings information and temporarily store them in Chroma
the database. Because it is stored temporarily, the above vectorized data will be lost when the above code is executed. If you want to use it next time, you need to calculate embeddings again, which is definitely not what we want.
In this case, we use Chroma
and Pinecone
these two databases to talk about how to persist vector data. For more LangChain databases, refer to this document .
1. Chroma
chroma
is a local vector database, and it provides one persist_directory
to set the persistent directory for persistence. When reading, you only need to call from_document
the method to load.
from langchain.vectorstores import Chroma
# 持久化数据
docsearch = Chroma.from_documents(documents, embeddings, persist_directory="D:/vector_store")
docsearch.persist()
# 加载数据
docsearch = Chroma(persist_directory="D:/vector_store", embedding_function=embeddings)
2. Pinecone
Pinecone is an online vector database. Therefore, I can still register as the first step, and then get the corresponding api key. (The free version will automatically clear the index if it is not used for 14 days.)
Then create our database:
- Index Name: This is optional
- Dimensions: OpenAI's text-embedding-ada-002 model is OUTPUT DIMENSIONS is 1536, so we fill in 1536 here
- Metric: default cosine
- Pod Type: choose starter plan
The code for persisting data and loading data is as follows
# 持久化数据
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)
A simple code to get embeddings from the database and answer is as follows
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)
3.6 Use the GPT3.5 model to build a question-and-answer robot for YouTube channels
After the chatgpt api (that is, GPT-3.5-Turbo) model came out, it was loved by everyone because it is better to live with less money, so LangChain also added a dedicated chain and model. Let's follow this example to see how to use it.
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.
-----------
{context}
-----------
{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'])
We can see that he can do a Q&A around this youtube video very accurately
It is also convenient to use streaming answers
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())
3.7 Connect thousands of tools with OpenAI
We mainly use zapier in combination to connect thousands of tools. So our first step is still to apply for an account and its natural language api key. After filling in the basic information of the zapier api key, you can basically see the approved email in the mailbox in seconds.
Then, we open our api configuration page through the connection in the right button. We click on the right Manage Actions
to configure which applications we want to use. I have configured the action of Gmail to read and send emails here, and all fields are selected to be guessed by AI.
After configuration, we start writing code
import os
os.environ["ZAPIER_NLA_API_KEY"] = ''
from langchain.llms import OpenAI
from langchain.agents import initialize_agent
from langchain.agents.agent_toolkits import ZapierToolkit
from langchain.utilities.zapier import ZapierNLAWrapper
llm = OpenAI(temperature=.3)
zapier = ZapierNLAWrapper()
toolkit = ZapierToolkit.from_zapier_nla_wrapper(zapier)
agent = initialize_agent(toolkit.get_tools(), llm, agent="zero-shot-react-description", verbose=True)
# 我们可以通过打印的方式看到我们都在 Zapier 里面配置了哪些可以用的工具
for tool in toolkit.get_tools():
print (tool.name)
print (tool.description)
print ("\n\n")
agent.run('请用中文总结最后一封"******@qq.com"发给我的邮件。并将总结发送给"******@qq.com"')
We can see that he successfully read ******@qq.com
the last email sent to him, and sent the summary to him ******@qq.com
. Here's what I sent to Gmail:
This is the email he sent to QQ mailbox:
This is just a small example, because zapier
there are thousands of applications, so we can easily combine openai api
to build our own workflow.
The main knowledge points have been explained, and some interesting small examples are used below as an extension.
4. Small example
4.1 Executing multiple chains
LangChain
It is chained, so he can also execute multiple chains in sequence:
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")
4.2 Structured output
Sometimes what we want to output is not text, but structured data like 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)
4.3 Crawl web pages and output JSON data
Sometimes we need to crawl somerelatively strong structurewebpage, and the information in the webpage needs to be returned in the form of JSON. We can use LLMRequestsChain
the class to achieve, for details, please refer to the following code
In order to facilitate understanding, I directly used the Prompt method to format the output results in the example, instead of using the format used in the previous case
StructuredOutputParser
, which can be regarded as providing another format idea
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'])
We can see that he output the formatted result very well
4.4 Customize the tools used in the agent
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?")
There is an interesting part in the custom tool. The weight of which tool is used is 工具中描述内容
realized by , which is completely different from the previous programming that used numerical values to control the weight.
For example, Calculator wrote in the description that if you ask questions about mathematics, use him as a tool. We can see in the above execution process that he chose the Calculator tool for calculation in the mathematics part of the prompt we requested.
4.5 Using Memory to implement a dialogue robot with memory
In the previous example, we used a custom list to store conversations to save history. Of course, you can also use the built-in memory object to achieve this.
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)
4.6 Using the Hugging Face model
Before using the Hugging Face model, you need to set the environment variable
import os
os.environ['HUGGINGFACEHUB_API_TOKEN'] = ''
Use the online Hugging Face model
from langchain import PromptTemplate, HuggingFaceHub, LLMChain
template = """Question: {question}
Answer: Let's think step by step."""
prompt = PromptTemplate(template=template, input_variables=["question"])
llm = HuggingFaceHub(repo_id="google/flan-t5-xl", model_kwargs={
"temperature":0, "max_length":64})
llm_chain = LLMChain(prompt=prompt, llm=llm)
question = "What NFL team won the Super Bowl in the year Justin Beiber was born?"
print(llm_chain.run(question))
Pull the Hugging Face model directly to local use
from langchain import PromptTemplate, LLMChain
from langchain.llms import HuggingFacePipeline
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline, AutoModelForSeq2SeqLM
model_id = 'google/flan-t5-large'
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForSeq2SeqLM.from_pretrained(model_id)
pipe = pipeline(
"text2text-generation",
model=model,
tokenizer=tokenizer,
max_length=100
)
local_llm = HuggingFacePipeline(pipeline=pipe)
print(local_llm('What is the capital of France? '))
template = """Question: {question} Answer: Let's think step by step."""
prompt = PromptTemplate(template=template, input_variables=["question"])
llm_chain = LLMChain(prompt=prompt, llm=local_llm)
question = "What is the capital of England?"
print(llm_chain.run(question))
The benefits of pulling the model to local use:
- training model
- Can use local GPU
- Some models don't work on Hugging Face
4.7 Execute SQL commands through natural language
Refer to the tutorials "Spark SQL Agent" and "SQL Database Agent"
We can implement the operation of executing SQL commands through SQLDatabaseToolkit
orSQLDatabaseChain
from langchain.agents import create_sql_agent
from langchain.agents.agent_toolkits import SQLDatabaseToolkit
from langchain.sql_database import SQLDatabase
from langchain.llms.openai import OpenAI
db = SQLDatabase.from_uri("sqlite:///../notebooks/Chinook.db")
toolkit = SQLDatabaseToolkit(db=db)
agent_executor = create_sql_agent(
llm=OpenAI(temperature=0),
toolkit=toolkit,
verbose=True
)
agent_executor.run("Describe the playlisttrack table")
from langchain import OpenAI, SQLDatabase, SQLDatabaseChain
db = SQLDatabase.from_uri("mysql+pymysql://root:[email protected]/chinook")
llm = OpenAI(temperature=0)
db_chain = SQLDatabaseChain(llm=llm, database=db, verbose=True)
db_chain.run("How many employees are there?")
V. Summary
All the cases are basically over, I hope you can gain something through the study of this article. This article is just a preliminary explanation of LangChain. I hope you will continue to explore the advanced functions. I hope that everyone can combine LangChain to develop more creative products, not just a bunch of products that build chatgpt chat clients with one click.