目标

今天咱们介绍一下如何使用 LangChain 构建一个简单的 LLM 应用程序。

这个应用程序能够将英文文本翻译成其他语言。

这是一个相对简单的 LLM 应用程序 —— 它仅包含一个 LLM 调用和一些提示。

今天的学习目的是初步了解下面的概念

  • 使用语言模型 (必须)
  • 使用 PromptTemplates 和 OutputParsers(必须)
  • 使用 LangChain 表达式语言 (LCEL) 将组件连接在一起(必须)
  • 使用 LangSmith 调试和跟踪您的应用程序 (不用也问题不大)
  • 使用 LangServe 部署您的应用程序(不用也问题不大)

准备阶段

我们全程使用windows + python, 其他的方法就不介绍了,同学们可以自己探索~

安装

1
pip install langchain

关于 Jupyter Notebook

咱们用能跑python的编程工具就可以,用什么来跑不是很重要-。-

LangSmith

langsmith 是一个可以跟踪runnable 的工具,可以跟踪和记录复杂流程中的大部分参数,对于复杂问题分析很有帮助。在学习初期,我们可以先不使用这个工具,到后面遇到复杂逻辑和chain的时候,我们再使用。 感兴趣的同学可以自己去注册一下,每月有免费的使用额度。

薅羊毛 langsmith 的提示:截止2024 7.1日前,免费账户每月有5K 的使用次数

New Pricing:All free accounts will be rate limited to 5k traces per month starting on July 1st. To avoid this, sign up for our paid plans

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
你可以这样简单使用
# 新建一个ID号,用于记录你的Log
unique_id = uuid4().hex[0:8]

# 写一个TAG
os.environ["LANGCHAIN_PROJECT"] = f" Agent RAG - {unique_id}"

# 这个表示你要使用langsmith 开始记录,不用就false
os.environ["LANGCHAIN_TRACING_V2"] = 'true'

# 这个是你注册langsmith 后的KEY
# 你可以把你的key 放到环境中,用MY_LANGCHAIN_API_KEY来引用
os.environ["LANGCHAIN_API_KEY"] = os.getenv('MY_LANGCHAIN_API_KEY')

# 要是你觉得麻烦 你就这样
os.environ["LANGCHAIN_API_KEY"] = 'dsad6487dfdhb... 你的key'

使用语言模型

官网列出一堆模型,好是好,国内能用的没几个…(不翻墙的情况)

我们先用官网中的 Azure OpenAi 以及 千帆来做演示~

创建一个 Azure OpenAi chatModel

1
2
3
4
5
6
os.environ["AZURE_OPENAI_API_KEY"] =AZURE_OPENAI_API_KEY
os.environ["AZURE_OPENAI_ENDPOINT"] =AZURE_OPENAI_ENDPOINT
gpt3p5_model = AzureChatOpenAI(
openai_api_version="2024-02-15-preview",
azure_deployment=DEPLOYMENT_NAME_GPT3P5,
)

AZURE_OPENAI_API_KEY: 你的Azure OpenAI KEY, 需要在微软Azure中申请订阅

AZURE_OPENAI_ENDPOINT: 你的服务端endpit,一个url地址,订阅后从Azure获取

openai_api_version: 你使用模型的版本号,依赖你使用的模型

azure_deployment:你给你部署的模型起的名字,从Azure获取

给出提示词,并调用invoke (LCEL 的方法之一)

1
2
3
4
5
6
7
messages = [
SystemMessage(content="Translate the following from English into Italian"),
HumanMessage(content="hi!"),
]

res = gpt3p5_model.invoke(messages)
print(res.content)

messages: 消息列表,通常包含整个对话历史

SystemMessage:系统提示词,在messages 中一般只出现一次,表明系统的身份

HumanMessage: 用户消息

输出

模型输出的内容是 一个 AIMessage

1
2
3
AIMessage(content='ciao!....

content='Ciao!' response_metadata={'token_usage': {'completion_tokens': 3, 'prompt_tokens': 20, 'total_tokens': 23}, 'model_name': 'gpt-35-turbo', 'system_fingerprint': None, 'prompt_filter_results': [{'prompt_index': 0, 'content_filter_results': {'hate': {'filtered': False, 'severity': 'safe'}, 'self_harm': {'filtered': False, 'severity': 'safe'}, 'sexual': {'filtered': False, 'severity': 'safe'}, 'violence': {'filtered': False, 'severity': 'safe'}}}], 'finish_reason': 'stop', 'logprobs': None, 'content_filter_results': {'hate': {'filtered': False, 'severity': 'safe'}, 'self_harm': {'filtered': False, 'severity': 'safe'}, 'sexual': {'filtered': False, 'severity': 'safe'}, 'violence': {'filtered': False, 'severity': 'safe'}}} id='run-2340cccd-9b63-4b07-9dfd-3c154bbef121-0'

创建 文心一言4 chatModel

1
2
3
4
5
6
7
8
9
# 千帆的 AKSK, 需要我们去百度网站申请
os.environ["QIANFAN_AK"] = MY_QIANFAN_AK
os.environ["QIANFAN_SK"] = MY_QIANFAN_SK

# 文心一言4 模型ERNIE-Bot-4
wenxin4_model = QianfanChatEndpoint(model="ERNIE-Bot-4")
res = wenxin4_model.invoke(messages)
print(res.content)
pass

输出

1
2
AIMessage(content='salve!....
content='salve!' additional_kwargs={'finish_reason': 'normal', 'request_id': 'as-hpbfyf1uqr', 'object': 'chat.completion', 'search_info': [], 'function_call': {}, 'tool_calls': [{'type': 'function', 'function': {}}]} response_metadata={'token_usage': {'prompt_tokens': 10, 'completion_tokens': 3, 'total_tokens': 13}, 'model_name': 'ERNIE-Bot-4', 'finish_reason': 'normal', 'id': 'as-hpbfyf1uqr', 'object': 'chat.completion', 'created': 1718674042, 'result': 'salve!', 'is_truncated': False, 'need_clear_history': False, 'usage': {'prompt_tokens': 10, 'completion_tokens': 3, 'total_tokens': 13}} id='run-4f50bc84-86a6-46dd-8c6f-03d0fbafc3d5-0'

输出解析器

1
2
3
4
5
6
7
8
9
10
11
12
from langchain_core.output_parsers import StrOutputParser

parser = StrOutputParser()

# 大模型的输出
result = model.invoke(messages)

# 解析器 解析模型的输出
parser.invoke(result)

# 将 AIMessage 解析成 字符串 (这一步要理解一下...)
'Ciao!'

为了让上面几步连贯,这也是langchain 的 精华之一

1
2
# 使用 chain
chain = model | parser

于是 文心一言4 的chain, 可以这样

1
2
3
4
chain = wenxin4_model | parser
res = chain.invoke(messages)
print(res.content)
pass

使用提示词模板

我们可以在提示词中使用变量,变量的表示方法是把变量放到{ }中

系统提示词: 通过变量language, 我们可以改变目标语言的类型

1
system_template = "Translate the following into {language}:"

将用户输入,放入变量 text;组合成一个[]

1
2
3
prompt_template = ChatPromptTemplate.from_messages(
[("system", system_template), ("user", "{text}")]
)

通过invoke 方法,指定变量的内容

1
2
result = prompt_template.invoke({"language": "italian", "text": "hi"})
print(result.to_messages())

输出

1
messages=[SystemMessage(content='Translate the following into italian:'), HumanMessage(content='hi')]

将上面的各个部分组合起来: chain !

1
2
3
4
ful_chain = prompt_template | wenxin4_model | parser
res = ful_chain.invoke({"language": "italian", "text": "hi"})
print(res)
pass

初步体验一下 Langserve

核心

用 FastAPI 创建一个APP,再调用 langserve add_routes方法,将消息路由到chain 上,作为chain 的输入

需要安装

pip install sse_starlette

pip install langserve

文心4 作为模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env python
import os
from typing import List

from fastapi import FastAPI
from langchain_community.chat_models import QianfanChatEndpoint
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
from langserve import add_routes

from llm_cfg import MY_QIANFAN_AK, MY_QIANFAN_SK

# 1. Create prompt template
system_template = "Translate the following into {language}:"
prompt_template = ChatPromptTemplate.from_messages([
('system', system_template),
('user', '{text}')
])

# 2. Create model
os.environ["QIANFAN_AK"] = MY_QIANFAN_AK
os.environ["QIANFAN_SK"] = MY_QIANFAN_SK

# 千帆
model = QianfanChatEndpoint(model="ERNIE-Bot-4")

# 3. Create parser
parser = StrOutputParser()

# 4. Create chain
chain = prompt_template | model | parser


# 4. App definition
app = FastAPI(
title="LangChain Server",
version="1.0",
description="A simple API server using LangChain's Runnable interfaces",
)

# 5. Adding chain route

add_routes(
app,
chain,
path="/chain",
)

if __name__ == "__main__":
import uvicorn

uvicorn.run(app, host="localhost", port=8000)

直接运行main 方法,看到命令行成功后,浏览器中打开 :http://localhost:8000/chain/playground/

客户端调用服务端

有了上面的服务端,Langchain 可以支持远程chain的调用,小伙伴们可以自行尝试。

在单位里,小伙伴们可以自己建立一个大模型服务,然后让单位里的小伙伴调用~~

1
2
3
4
from langserve import RemoteRunnable

remote_chain = RemoteRunnable("http://localhost:8000/chain/")
remote_chain.invoke({"language": "italian", "text": "hi"})

代码附录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import os

from langchain_community.chat_models import QianfanChatEndpoint
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import AzureChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage

from llm_cfg import AZURE_OPENAI_API_KEY, AZURE_OPENAI_ENDPOINT, DEPLOYMENT_NAME_GPT3P5, MY_QIANFAN_AK, MY_QIANFAN_SK

if __name__ == '__main__':
os.environ["AZURE_OPENAI_API_KEY"] =AZURE_OPENAI_API_KEY
os.environ["AZURE_OPENAI_ENDPOINT"] =AZURE_OPENAI_ENDPOINT
gpt3p5_model = AzureChatOpenAI(
openai_api_version="2024-02-15-preview",
azure_deployment=DEPLOYMENT_NAME_GPT3P5,
)

messages = [
SystemMessage(content="Translate the following from English into Italian"),
HumanMessage(content="hi!"),
]

res = gpt3p5_model.invoke(messages)
print(res.content)
pass

os.environ["QIANFAN_AK"] = MY_QIANFAN_AK
os.environ["QIANFAN_SK"] = MY_QIANFAN_SK

# 千帆
wenxin4_model = QianfanChatEndpoint(model="ERNIE-Bot-4")
res = wenxin4_model.invoke(messages)
print(res.content)
pass

# 输出解析
from langchain_core.output_parsers import StrOutputParser

parser = StrOutputParser()

# chain
chain = wenxin4_model | parser
res = chain.invoke(messages)
print(res.content)
pass

# 提示词
system_template = "Translate the following into {language}:"
prompt_template = ChatPromptTemplate.from_messages(
[("system", system_template), ("user", "{text}")]
)
result = prompt_template.invoke({"language": "italian", "text": "hi"})
print(result.to_messages())
pass

ful_chain = prompt_template | wenxin4_model | parser
res = ful_chain.invoke({"language": "italian", "text": "hi"})
print(res)
pass