LangChain
- LangChain 是一套面向大模型的开发框架
- LangChain 是 AGI 时代软件工程的一个探索和原型
- 学习 LangChain 要关注接口变更
LangChain 的核心组件
- 模型 I/O 封装
- LLMs:大语言模型
- Chat Models:一般基于 LLMs,但按对话结构重新封装
- PromptTemple:提示词模板
- OutputParser:解析输出
- 数据连接封装
- Document Loaders:各种格式文件的加载器
- Document Transformers:对文档的常用操作,如:split,filter,translate,extract metadata,etc
- Text Embedding Models:文本向量化表示,用于检索等操作
- Verctorstores:(面向检索的)向量的存储
- Retrievers:向量的检索
- 对话历史管理
- 对话历史的存储、加载与剪裁
- 架构封装
- Chain:实现一个功能或者一系列顺序功能组合
- Agent:根据用户输入,自动规划执行步骤,自动选择每步需要的工具,最终完成用户指定的功能
- Tools:调用外部功能的函数,例如:调 google 搜索、文件 I/O、Linux Shell 等等
- Toolkits:操作某软件的一组工具集,例如:操作 DB、操作 Gmail 等等
- Callbacks
模型 I/O 封装
把不同的模型,统一封装成一个接口,方便更换模型而不用重构代码。
模型 API:LLM vs ChatModel
shell
pip install --upgrade langchain
pip install --upgrade langchain-openai
pip install --upgrade langchain-community
pip install --upgrade langchain
pip install --upgrade langchain-openai
pip install --upgrade langchain-community
OpenAI 模型封装
python
from langchain_openai import ChatOpenAI
# 保证操作系统的环境变量里面配置好了OPENAI_API_KEY,OPENAI_BASE_URL
llm = ChatOpenAI(model="gpt-40-mini")
response = llm.invoke("你是谁")
print(response.content)
from langchain_openai import ChatOpenAI
# 保证操作系统的环境变量里面配置好了OPENAI_API_KEY,OPENAI_BASE_URL
llm = ChatOpenAI(model="gpt-40-mini")
response = llm.invoke("你是谁")
print(response.content)
这样就能简单调用一个模型
多轮对话 Session 封装
python
from langchain.schema import {
AIMessage, # 等价于OpenAI接口中的assistant role
HumanMessage, # 等价于OpenAI接口中的user role
SystemMessage # 等价于OpenAI接口中的system role
}
messages = [
SystemMessage(content="你是助理"),
HumanMessage(content="我是老板"),
AIMessage(content="欢迎"),
HumanMessage(content="我是谁")
]
ret = llm.invoke(messages)
print(ret.content)
from langchain.schema import {
AIMessage, # 等价于OpenAI接口中的assistant role
HumanMessage, # 等价于OpenAI接口中的user role
SystemMessage # 等价于OpenAI接口中的system role
}
messages = [
SystemMessage(content="你是助理"),
HumanMessage(content="我是老板"),
AIMessage(content="欢迎"),
HumanMessage(content="我是谁")
]
ret = llm.invoke(messages)
print(ret.content)
模型的输入与输出
Prompt 模板封装
- PromptTemplate 可以在模板中自定义变量
python
from langchain.prompts import PromptTemplate
template = PromptTemplate.from_template("给我讲个关于{subject}的笑话")
print(template.format(subject='小明'))
from langchain.prompts import PromptTemplate
template = PromptTemplate.from_template("给我讲个关于{subject}的笑话")
print(template.format(subject='小明'))
- ChatPromptTemplate 用模板表示的对话上下文
python
from langchain.prompts import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
SystemMessagePromptTemplate,
)
from langchain_openai import ChatOpenAI
template = ChatPromptTemplate.from_messages(
[
SystemMessagePromptTemplate.from_template("你是{product}的客服助手。你的名字叫{name}"),
HumanMessagePromptTemplate.from_template("{query}"),
]
)
llm = ChatOpenAI(model="gpt-4o-mini")
prompt = template.format_messages(
product="AI研究院",
name="大吉",
query="你是谁"
)
print(prompt)
ret = llm.invoke(prompt)
print(ret.content)
from langchain.prompts import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
SystemMessagePromptTemplate,
)
from langchain_openai import ChatOpenAI
template = ChatPromptTemplate.from_messages(
[
SystemMessagePromptTemplate.from_template("你是{product}的客服助手。你的名字叫{name}"),
HumanMessagePromptTemplate.from_template("{query}"),
]
)
llm = ChatOpenAI(model="gpt-4o-mini")
prompt = template.format_messages(
product="AI研究院",
name="大吉",
query="你是谁"
)
print(prompt)
ret = llm.invoke(prompt)
print(ret.content)
- MessagesPlaceholder 把多轮对话变成模板
python
from langchain.prompts import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
MessagesPlaceholder,
)
human_prompt = "Translate your answer to {language}."
human_message_template = HumanMessagePromptTemplate.from_template(human_prompt)
chat_prompt = ChatPromptTemplate.from_messages(
# variable_name 是 message placeholder 在模板中的变量名
# 用于在赋值时使用
[MessagesPlaceholder("history"), human_message_template]
)
from langchain.prompts import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
MessagesPlaceholder,
)
human_prompt = "Translate your answer to {language}."
human_message_template = HumanMessagePromptTemplate.from_template(human_prompt)
chat_prompt = ChatPromptTemplate.from_messages(
# variable_name 是 message placeholder 在模板中的变量名
# 用于在赋值时使用
[MessagesPlaceholder("history"), human_message_template]
)
python
from langchain_core.messages import AIMessage, HumanMessage
human_message = HumanMessage(content="Who is Elon Musk?")
ai_message = AIMessage(
content="Elon Musk is a billionaire entrepreneur, inventor, and industrial designer"
)
messages = chat_prompt.format_prompt(
# 对 "history" 和 "language" 赋值
history=[human_message, ai_message], language="中文"
)
print(messages.to_messages())
from langchain_core.messages import AIMessage, HumanMessage
human_message = HumanMessage(content="Who is Elon Musk?")
ai_message = AIMessage(
content="Elon Musk is a billionaire entrepreneur, inventor, and industrial designer"
)
messages = chat_prompt.format_prompt(
# 对 "history" 和 "language" 赋值
history=[human_message, ai_message], language="中文"
)
print(messages.to_messages())
python
result = llm.invoke(messages)
print(result.content)
result = llm.invoke(messages)
print(result.content)
从文件加载 Prompt 模板
python
from langchain.prompts import PromptTemplate
template = PromptTemplate.from_file("example_prompt_template.txt")
print("===Template===")
print(template)
print("===Prompt===")
print(template.format(topic='黑色幽默'))
from langchain.prompts import PromptTemplate
template = PromptTemplate.from_file("example_prompt_template.txt")
print("===Template===")
print(template)
print("===Prompt===")
print(template.format(topic='黑色幽默'))
结构化输出
直接输出 Pydantic 对象
python
from pydantic import BaseModel, Field
# 定义你的输出对象
class Date(BaseModel):
year: int = Field(description="Year")
month: int = Field(description="Month")
day: int = Field(description="Day")
era: str = Field(description="BC or AD")
from pydantic import BaseModel, Field
# 定义你的输出对象
class Date(BaseModel):
year: int = Field(description="Year")
month: int = Field(description="Month")
day: int = Field(description="Day")
era: str = Field(description="BC or AD")
python
from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import PydanticOutputParser
model_name = 'gpt-4o-mini'
temperature = 0
llm = ChatOpenAI(model_name=model_name, temperature=temperature)
# 定义结构化输出的模型
structured_llm = llm.with_structured_output(Date)
template = """提取用户输入中的日期。
用户输入:
{query}"""
prompt = PromptTemplate(
template=template,
)
query = "2024年十二月23日天气晴..."
input_prompt = prompt.format_prompt(query=query)
structured_llm.invoke(input_prompt)
from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import PydanticOutputParser
model_name = 'gpt-4o-mini'
temperature = 0
llm = ChatOpenAI(model_name=model_name, temperature=temperature)
# 定义结构化输出的模型
structured_llm = llm.with_structured_output(Date)
template = """提取用户输入中的日期。
用户输入:
{query}"""
prompt = PromptTemplate(
template=template,
)
query = "2024年十二月23日天气晴..."
input_prompt = prompt.format_prompt(query=query)
structured_llm.invoke(input_prompt)
输出指定格式的 JSON
python
json_schema = {
"title": "Date",
"description": "Formated date expression",
"type": "object",
"properties": {
"year": {
"type": "integer",
"description": "year, YYYY",
},
"month": {
"type": "integer",
"description": "month, MM",
},
"day": {
"type": "integer",
"description": "day, DD",
},
"era": {
"type": "string",
"description": "BC or AD",
},
},
}
structured_llm = llm.with_structured_output(json_schema)
structured_llm.invoke(input_prompt)
json_schema = {
"title": "Date",
"description": "Formated date expression",
"type": "object",
"properties": {
"year": {
"type": "integer",
"description": "year, YYYY",
},
"month": {
"type": "integer",
"description": "month, MM",
},
"day": {
"type": "integer",
"description": "day, DD",
},
"era": {
"type": "string",
"description": "BC or AD",
},
},
}
structured_llm = llm.with_structured_output(json_schema)
structured_llm.invoke(input_prompt)
使用 OutputParser
OutputParser 可以按指定格式解析模型的输出
python
from langchain_core.output_parsers import JsonOutputParser
parser = JsonOutputParser(pydantic_object=Date)
prompt = PromptTemplate(
template="提取用户输入中的日期。\n用户输入:{query}\n{format_instructions}",
input_variables=["query"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
input_prompt = prompt.format_prompt(query=query)
output = llm.invoke(input_prompt)
print("原始输出:\n"+output.content)
print("\n解析后:")
parser.invoke(output)
from langchain_core.output_parsers import JsonOutputParser
parser = JsonOutputParser(pydantic_object=Date)
prompt = PromptTemplate(
template="提取用户输入中的日期。\n用户输入:{query}\n{format_instructions}",
input_variables=["query"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
input_prompt = prompt.format_prompt(query=query)
output = llm.invoke(input_prompt)
print("原始输出:\n"+output.content)
print("\n解析后:")
parser.invoke(output)
也可以用 PydanticOutputParser
python
from langchain_core.output_parsers import PydanticOutputParser
parser = PydanticOutputParser(pydantic_object=Date)
input_prompt = prompt.format_prompt(query=query)
output = llm.invoke(input_prompt)
print("原始输出:\n"+output.content)
print("\n解析后:")
parser.invoke(output)
from langchain_core.output_parsers import PydanticOutputParser
parser = PydanticOutputParser(pydantic_object=Date)
input_prompt = prompt.format_prompt(query=query)
output = llm.invoke(input_prompt)
print("原始输出:\n"+output.content)
print("\n解析后:")
parser.invoke(output)