happy path#
# 启动之前需要在命令行执行
pip install -r requirements.txt
做什么?#
让LLM做翻译
使用LLM#
import os
from langchain_openai import ChatOpenAI
# os.environ["OPENAI_API_KEY"] = "sk-********" 去掉注释
# os.environ["OPENAI_API_BASE"] = "https://ai-yyds.com/v1"
model = ChatOpenAI(model="gpt-4")
到此,创建了ChatOpenAI的model,他继承了langchain的RunnableSerializable
接口,RunnableSerializable
在langchain的表达式中很重要,他重写了 __or__
方法,使得可以用 | 来实现管道符,并且规定了一系列标准方法,langchain的核心组件都实现了这个方法。之后细讲。在这里,就可以直接通过invoke方法来调用了。
model.invoke("hi,你是谁")
AIMessage(content='你好,我是OpenAI的人工智能助手。我可以帮助回答问题,提供信息,或者进行各种对话。你有什么需要帮助的吗?', response_metadata={'token_usage': {'completion_tokens': 55, 'prompt_tokens': 13, 'total_tokens': 68}, 'model_name': 'gpt-4', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-8bd37862-d050-4058-aa74-e168c96e44d1-0', usage_metadata={'input_tokens': 13, 'output_tokens': 55, 'total_tokens': 68})
如上所属,这种方式和之前直接调用openAI的接口是一样的,但是需要注意的是,返回值langchain做了包装,并且将入参也包装了, 将str
变为PromptValue
在和LLM交互的时候需要角色扮演,这里也支持,用下面的方式
from langchain_core.messages import HumanMessage, SystemMessage
messages = [
SystemMessage(content="将下面的英文歌词翻译为中文"),
HumanMessage(content="""
Look how they shine for you
And everything you do
Yeah' they were all Yellow
I came along
I wrote a song for you
And all the things you do
It was called Yellow
So then I took my turn
Oh what a thing to have done
""")]
# 传递给LLM
res = model.invoke(messages)
print(res)
content='看它们如何为你闪耀\n和你做的一切\n是的,它们都是黄色的\n我来了\n我为你写了一首歌\n和你做的所有事情\n那首歌被叫做黄色\n然后我轮到我了\n哦,这是多么伟大的事情\n' response_metadata={'token_usage': {'completion_tokens': 96, 'prompt_tokens': 87, 'total_tokens': 183}, 'model_name': 'gpt-4', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-74b64201-7eda-41ee-8f3a-42a105be083c-0' usage_metadata={'input_tokens': 87, 'output_tokens': 96, 'total_tokens': 183}
返回值解析#
现在需要从返回的AIMessage
中拿到返回值,langchain已经帮我们封装好了StrOutputParser
,可以直接读取到content
属性
from langchain_core.output_parsers import StrOutputParser
parser = StrOutputParser()
parser.invoke(res)
'看它们如何为你闪耀\n和你做的一切\n是的,它们都是黄色的\n我来了\n我为你写了一首歌\n和你做的所有事情\n那首歌被叫做黄色\n然后我轮到我了\n哦,这是多么伟大的事情\n'
如你看到的一样,StrOutputParser
也继承了RunnableSerializable
类,所以也可以通过invoke来调用。
到这里已经拿到了结果了。前面说了,继承于RunnableSerializable
的类,都可以通过 |
符号来实现管道流。 上面的代码就可以改写为
chain = model | parser
chain.invoke(messages)
'看他们如何为你闪耀\n以及你做的一切\n是的,他们都是黄色的\n我出现了\n我为你写了一首歌\n和你做的所有事情\n这首歌叫黄色\n那么我轮到我了\n哦,做这件事真是太棒了'
体会到chain的意义了吗!! 不需要像之前一样,先组装prompt,在去调用llm的接口,自己做解析。langchain已经做好这样的功能了,我们做的事情是将组件拼接在一块,形成一个chain。快捷开发
但是现在还有个问题,prompt不够灵活,如果想翻译为韩文的话,要怎么做
Prompt Templates#
PromptTemplates 是 LangChain 中的一个重要概念,他可以做格式化模板,将消息分类(系统message,人类的message,ai的message) 对于上面,需要有两个模板变量
language: 翻译为什么语言
input:要翻译的文本
下面用ChatPromptTemplate
来做,他是BasePromptTemplate
的子类,用于创建灵活的聊天模型模板prompt
from langchain_core.prompts import ChatPromptTemplate
# 定义system message
system_template = "将下面的文本翻译为{language}:"
# 创建 ChatPromptTemplate,分为user和system
prompt_template = ChatPromptTemplate.from_messages(
[("system", system_template), ("user", "{input}")]
)
ChatPromptTemplate
继承了RunnableSerializable
,可以直接调用invoke
方法
prompt_format_res = prompt_template.invoke({"language":"韩文","input":"""
Look how they shine for you
And everything you do
Yeah' they were all Yellow
I came along
I wrote a song for you
And all the things you do
It was called Yellow
So then I took my turn
Oh what a thing to have done
"""})
print(prompt_format_res)
type(prompt_format_res)
messages=[SystemMessage(content='将下面的文本翻译为韩文:'), HumanMessage(content="\nLook how they shine for you\nAnd everything you do\nYeah' they were all Yellow\nI came along\nI wrote a song for you\nAnd all the things you do\nIt was called Yellow\nSo then I took my turn\nOh what a thing to have done\n")]
langchain_core.prompt_values.ChatPromptValue
如上所示,prompt_template 调用 invoke
之后,得到的类型是ChatPromptValue
,调用messages
拿到messages,如下所示,这就和👆🏻是一样的。不过,灵活性大大提升
prompt_format_res.messages
[SystemMessage(content='将下面的文本翻译为韩文:'),
HumanMessage(content="\nLook how they shine for you\nAnd everything you do\nYeah' they were all Yellow\nI came along\nI wrote a song for you\nAnd all the things you do\nIt was called Yellow\nSo then I took my turn\nOh what a thing to have done\n")]
它也实现了RunnableSerializable
接口,所以可以用|
拼接
llm = prompt_template | model | parser
invoke_res = llm.invoke({"language":"韩文","input":"""
Look how they shine for you
And everything you do
Yeah' they were all Yellow
I came along
I wrote a song for you
And all the things you do
It was called Yellow
So then I took my turn
Oh what a thing to have done
"""})
print(invoke_res)
And it was all Yellow
Your
韩文看不懂,把韩文翻译为中文
llm.invoke({"language":"中文","input":invoke_res})
'而所有的都是黄色的\n你的'
!!看到了么,一个完整的chain出现了,prompt -> llm -> result parse。并且用|
连接了起来,实现了管道流。(是因为他们都继承了RunnableSerializable
类),和原始的openai的chat api相比,代码简单了很多,灵活性也很高。
到这里happy path 结束了
上面支持开发,langchain是一站式的llm开发框架,下面介绍langsmith和langserver
lang server#
就是将chain通过REST api的形式暴露出来,并且提供了swagger文档和playground来调试chain
# ! pip install "langserve[all]"
# 我已经在requirements.txt中已经安装过了,这里不需要了
他是基于FAST API的,这里需要创建fast的app,绑定路由,启动。
import uvicorn
from fastapi import FastAPI
from langserve import add_routes
# 创建FastAPi app
app = FastAPI(
title="LangChain Server",
version="1.0",
description="A simple API server using LangChain's Runnable interfaces",
)
# 创建chain
def translate_chain():
# 将上面的代码包装在这里
import os
from langchain_openai import ChatOpenAI
# os.environ["OPENAI_API_KEY"] = "sk-********"
# os.environ["OPENAI_API_BASE"] = "https://ai-yyds.com/v1"
model = ChatOpenAI(model="gpt-4")
from langchain_core.output_parsers import StrOutputParser
parser = StrOutputParser()
from langchain_core.prompts import ChatPromptTemplate
# 定义system message
system_template = "将下面的文本翻译为{language}:"
# 创建 ChatPromptTemplate,分为user和system
prompt_template = ChatPromptTemplate.from_messages(
[("system", system_template), ("user", "{input}")]
)
return prompt_template | model | parser
# 绑定chain
add_routes(
app,
translate_chain(),
path="/chain",
)
print("这里的代码需要新建一个py文件来跑,因为jupyter-book里面不能再启动event loop了")
# if __name__ == '__main__':
# # 启动
# uvicorn.run(app, host="localhost", port=8000)
这里的代码需要新建一个py文件来跑,因为jupyter-book里面不能再启动event loop了
上面的代码需要新建一个py文件来跑,因为jupyter-book里面不能再启动event loop了,具体可以看 src/section_1_lang_server.py
他提供了功能如下
将chain暴露为了REST API并且提供了swagger文档#
服务地址: http://localhost:8000 接口文档地址:http://localhost:8000/docs
提供了playground来调试#
地址:http://localhost:8000/chain/playground/
运行调试:
lang smith#
官网: https://docs.smith.langchain.com/ lang Smith来监控上面的chain。在使用之前需要安装,配置api_key(api_key 在lang smith官网中配置就行)
export LANGCHAIN_TRACING_V2=true
export LANGCHAIN_API_KEY=<your-api-key>
配置之后,再次运行上面的结果,可以很清晰的看到chain的运行过程,可以如下
到此,happy path已经完成了,回顾一下,在这个例子中,了解到
LangChain Expression Language(LangChain的表达式)
Prompt Template
Chat Models
Output Parsers
Lang Server
Lang Smith
在之后的学习中,我会按照上面的顺序来学习分享,此外还会增加一些例子。💪🏻