介绍
使用 langchain 框架,调用通义千问大模型,构建一个简单的 LLM 应用程序
本文中出现的每段代码都是可以完整执行的
注意
大语言模型和各类框架迭代飞快,再看本文时,部分代码可能已经过时了
本文所用到的 python 包 | 版本 |
---|---|
dashscope | 1.20.3 |
langchain | 0.2.12 |
langchain-community | 0.2.11 |
langserve | 0.2.2 |
配置环境变量
申请通义千问的 API KEY:https://dashscope.console.aliyun.com/
在项目中创建一个 .env
文件,保存程序运行时所需的环境变量:
(或者你用其他方式保存环境变量也行)
# 把通义千问的 API KEY 放这里
DASHSCOPE_API_KEY="sk-xxxx"
程序运行时,使用 dotenv.load_dotenv()
从 .env
文件中加载环境变量
pip install python-dotenv
import os
import dotenv
# 从文件中加载运行程序所需的环境变量
dotenv.load_dotenv(".env")
print(os.getenv("DASHSCOPE_API_KEY"))
快速开始
通义千问是阿里云研发的大语言模型;灵积是阿里云推出的模型服务平台,DashScope 是灵积的英文名
langchain 把与第三方大模型的集成都放在了 langchain_community 这个包中,其中就有通义千问大模型
pip install dashscope
pip install langchain
pip install langchain_community
将一段字符串传递给 .invoke()
,实现简单的对话:
from langchain_community.chat_models import ChatTongyi
import dotenv
dotenv.load_dotenv(".env")
model = ChatTongyi(model="qwen-turbo")
response = model.invoke("你好,请问你是谁?")
print(response.content)
也可以将消息列表传递给 .invoke()
:
from langchain_community.chat_models import ChatTongyi
import dotenv
dotenv.load_dotenv(".env")
model = ChatTongyi(model="qwen-turbo")
messages = [
("system", "请你扮演一名翻译助手"),
("user", "你好,请问你是谁?")
]
response = model.invoke(messages)
print(response.content)
prompt template
prompt(提示)是给大模型的输入,上述示例中传入 .invoke()
的参数就是 prompt
prompt 不是只有用户的输入,还能含有系统预设、角色信息、历史对话等内容
from langchain.prompts import ChatPromptTemplate
# 创建模板
prompt_template = ChatPromptTemplate.from_messages([
("system", "将下列文本翻译成{language}"),
("user", "{text}")
])
# 渲染模板成字符串
str_prompt = prompt_template.format(
language="中文",
text="Hello, how are you?"
)
# 渲染模板成消息列表
messages_prompt = prompt_template.invoke({
"language": "中文",
"text": "Hello, how are you?"}
)
print(str_prompt, end="\n--------\n")
print(messages_prompt)
根据需要渲染模板,让模型完成不同的翻译工作
from langchain.prompts import ChatPromptTemplate
from langchain_community.chat_models import ChatTongyi
import dotenv
dotenv.load_dotenv(".env")
model = ChatTongyi(model="qwen-turbo")
prompt_template = ChatPromptTemplate.from_messages([
("system", "将下列文本翻译成{language}"),
("user", "{text}")
])
def translate(text: str, language: str) -> str:
prompt = prompt_template.invoke({"language": text, "text": language})
response = model.invoke(prompt)
return response.content
print(translate("Hello, how are you?", "中文"))
print(translate("你是谁?", "英文"))
chain、LCEL
使用 |
运算符将 prompt_template.invoke() -> model.invoke()
的流程封装成一个链
这种将 LangChain 组件的以声明式的方式链接在一起的写法,叫 LCEL(LangChain Expression Language)
直接调用 chain.invoke()
,便相当于依次调用了 prompt_template.invoke()
和 model.invoke()
from langchain.prompts import ChatPromptTemplate
from langchain_community.chat_models import ChatTongyi
import dotenv
dotenv.load_dotenv(".env")
model = ChatTongyi(model="qwen-turbo")
prompt_template = ChatPromptTemplate.from_messages([
("system", "请将下列文本翻译成{language}"),
("user", "{text}")
])
# 将组件链接在一起
chain = prompt_template | model
response = chain.invoke({"language": "今天天气真好", "text": "英文"})
print(response.content)
output parser
定义一个 my_log()
函数,用于输出每次对话的 token 消耗情况
from langchain.prompts import ChatPromptTemplate
from langchain_community.chat_models import ChatTongyi
import dotenv
dotenv.load_dotenv(".env")
model = ChatTongyi(model="qwen-turbo")
prompt_template = ChatPromptTemplate.from_messages([
("system", "请将下列文本翻译成{language}"),
("user", "{text}")
])
chain = prompt_template | model
def my_log(chain_output):
# 输出本次问答的 token 消耗情况
print(f"\033[35m[info] token_usage: {chain_output.response_metadata['token_usage']}\033[0m")
return chain_output
def translate(text, language):
response = chain.invoke({"language": language, "text": text})
my_log(response)
return response.content
print(translate("今天天气真好", "英文"))
上述示例中,我们对模型的输出做了两层处理:一是打印输出 token 消耗情况,二是通过 .content
拿到模型的输出文本内容。我们可以将这两层处理封装成一个函数
langchain 把用作“解析模型输出”的函数叫做 output parser
output parser 也可以通过 |
加入到链中,这时调用 chain.invoke()
所拿到的的结果,就是经过 output parser 处理的结果
from langchain.prompts import ChatPromptTemplate
from langchain_community.chat_models import ChatTongyi
import dotenv
dotenv.load_dotenv(".env")
model = ChatTongyi(model="qwen-turbo")
prompt_template = ChatPromptTemplate.from_messages([
("system", "请将下列文本翻译成{language}"),
("user", "{text}")
])
def my_output_parser(model_output):
print(f"\033[35m[info] token_usage: {model_output.response_metadata['token_usage']}\033[0m")
return model_output.content
chain = prompt_template | model | my_output_parser
print(chain.invoke({"language": "今天天气真好", "text": "英文"}))
小结
在 LangChain 中,prompt template、model、output parser 是构建和执行链条的三个关键组件
prompt template 用来处理输入,output parser 用来处理输出
output parser 中也可以调用其他 chain 来处理当前 model 返回的结果
部署
LangServe 帮助开发者将 LangChain 链部署为 REST API
pip install "langserve[all]"
from fastapi import FastAPI
from langchain_core.output_parsers import StrOutputParser
from langchain_community.chat_models import ChatTongyi
from langchain.prompts import ChatPromptTemplate
import langserve
import dotenv
dotenv.load_dotenv(".env")
prompt_template = ChatPromptTemplate.from_messages([
("system", "将下列文本翻译成{language},你只需返回翻译结果,不要返回其他内容"),
("user", "{text}")
])
model = ChatTongyi(model="qwen-turbo")
chain = prompt_template | model | StrOutputParser()
app = FastAPI(title="翻译")
langserve.add_routes(app, chain, path="/translate")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="localhost", port=8000)