LangChain 37 深入理解LangChain 表达式语言二 实现prompt+model+output parser LangChain Expression Language (LCEL)

2023-12-27 15:44:09

LangChain系列文章

  1. LangChain 实现给动物取名字
  2. LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字
  3. LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄
  4. LangChain 4用向量数据库Faiss存储,读取YouTube的视频文本搜索Indexes for information retrieve
  5. LangChain 5易速鲜花内部问答系统
  6. LangChain 6根据图片生成推广文案HuggingFace中的image-caption模型
  7. LangChain 7 文本模型TextLangChain和聊天模型ChatLangChain
  8. LangChain 8 模型Model I/O:输入提示、调用模型、解析输出
  9. LangChain 9 模型Model I/O 聊天提示词ChatPromptTemplate, 少量样本提示词FewShotPrompt
  10. LangChain 10思维链Chain of Thought一步一步的思考 think step by step
  11. LangChain 11实现思维树Implementing the Tree of Thoughts in LangChain’s Chain
  12. LangChain 12调用模型HuggingFace中的Llama2和Google Flan t5
  13. LangChain 13输出解析Output Parsers 自动修复解析器
  14. LangChain 14 SequencialChain链接不同的组件
  15. LangChain 15根据问题自动路由Router Chain确定用户的意图
  16. LangChain 16 通过Memory记住历史对话的内容
  17. LangChain 17 LangSmith调试、测试、评估和监视基于任何LLM框架构建的链和智能代理
  18. LangChain 18 LangSmith监控评估Agent并创建对应的数据库
  19. LangChain 19 Agents Reason+Action自定义agent处理OpenAI的计算缺陷
  20. LangChain 20 Agents调用google搜索API搜索市场价格 Reason Action:在语言模型中协同推理和行动
  21. LangChain 21 Agents自问自答与搜索 Self-ask with search
  22. LangChain 22 LangServe用于一键部署LangChain应用程序
  23. LangChain 23 Agents中的Tools用于增强和扩展智能代理agent的功能
  24. LangChain 24 对本地文档的搜索RAG检索增强生成Retrieval-augmented generation
  25. LangChain 25: SQL Agent通过自然语言查询数据库sqlite
  26. LangChain 26: 回调函数callbacks打印prompt verbose调用
  27. LangChain 27 AI Agents角色扮演多轮对话解决问题CAMEL
  28. LangChain 28 BabyAGI编写旧金山的天气预报
  29. LangChain 29 调试Debugging 详细信息verbose
  30. LangChain 30 ChatGPT LLM将字符串作为输入并返回字符串Chat Model将消息列表作为输入并返回消息
  31. LangChain 31 模块复用Prompt templates 提示词模板
  32. LangChain 32 输出解析器Output parsers
  33. LangChain 33: LangChain表达语言LangChain Expression Language (LCEL)
  34. LangChain 34: 一站式部署LLMs使用LangServe
  35. LangChain 35: 安全最佳实践深度防御Security
  36. LangChain 36 深入理解LangChain 表达式语言优势一 LangChain Expression Language (LCEL)

在这里插入图片描述

LangChain Expression Language (LCEL)使得从基本组件构建复杂链变得简单,并支持流式处理、并行处理和日志记录等开箱即用的功能。

1. Basic example: prompt + model + output parser

最基本和常见的用例是将提示模板和模型链接在一起。要看看这是如何工作的,让我们创建一个链条,输入一个主题然后生成一个笑话:

from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

from dotenv import load_dotenv  

load_dotenv()  

prompt = ChatPromptTemplate.from_template("给我讲个关于{topic}的短篇笑话。")
model = ChatOpenAI()
output_parser = StrOutputParser()

chain = prompt | model | output_parser

respose = chain.invoke({"topic": "冰淇淋"})
print('joke >> ', respose)

输出

zgpeace@zgpeaces-MacBook-Pro:~/Workspace/LLM/langchain-llm-app(develop?) ? python LCEL/pipe_operator.py
joke >>  有一天,冰淇淋和巧克力一起去参加派对。冰淇淋非常兴奋地对巧克力说:“今天真是个美好的日子!我们可以尽情享受派对,还能交到很多新朋友!”
巧克力笑着回答道:“是啊,我也觉得很开心。不过,我希望派对上没有巧克力味的冰淇淋。”
冰淇淋一听,惊讶地问:“为什么?你不喜欢和我一起参加派对吗?”
巧克力笑容满面地解释说:“当然不是!我只是觉得,如果有太多巧克力味的冰淇淋,那会让我觉得自己是个传说中的巧克力涂鸦,而不是独一无二的巧克力块。”
冰淇淋听后,哈哈大笑:“原来你是担心自己会被错认,真是个巧克力的狂热爱好者!”

zgpeace@zgpeaces-MacBook-Pro:~/Workspace/LLM/langchain-llm-app(develop?) ? python LCEL/pipe_operator.py
joke >>  一天,一位小男孩走进一家冰淇淋店。他对店员说:“请给我一杯冰淇淋,但是我只能付1美元。”

店员微笑着回答:“当然可以,小伙子。我们有一种特别的冰淇淋,叫做‘奇迹冰淇淋’,只要1美元就可以买到。”

小男孩很开心地接过冰淇淋,但发现冰淇淋非常小,只有一小勺。他有点失望地问:“这才是‘奇迹冰淇淋’吗?”

店员笑着说:“没错,这是‘奇迹冰淇淋’。你知道为什么吗?因为只要一小勺,你就会觉得它非常好吃,吃完后还会有一美元留在口袋里!”

请注意这行代码,我们使用LCEL将不同的组件拼接成一个单一的链。

chain = prompt | model | output_parser

竖线符号|类似于Unix管道操作符,它将不同组件链接在一起,将一个组件的输出作为下一个组件的输入。

在这个链条中,用户输入被传递到提示模板,然后提示模板的输出被传递到模型,然后模型的输出被传递到输出解析器。让我们分别看看每个组件,真正理解发生了什么。

2. Prompt

“prompt”是一个BasePromptTemplate,意味着它接受一个模板变量的字典并生成一个PromptValuePromptValue是一个封装完成的提示的包装器,可以传递给LLM(以字符串作为输入)或ChatModel(以消息序列作为输入)。它可以与任何语言模型类型一起使用,因为它定义了生成BaseMessages和生成字符串的逻辑。

prompt_value = prompt.invoke({"topic": "ice cream"})
print('prompt_value >> ', prompt_value)

运行结果:

prompt_value >>  messages=[HumanMessage(content='给我讲个关于ice cream的短篇笑话。')]
message = prompt_value.to_messages()
print('message >> ', message)

运行结果:

message >>  [HumanMessage(content='给我讲个关于ice cream的短篇笑话。')]
string = prompt_value.to_string()
print('string >> ', string)

运行结果:

string >>  Human: 给我讲个关于ice cream的短篇笑话。

3. Model

PromptValue然后传递给模型。在这种情况下,我们的模型是ChatModel,这意味着它将输出BaseMessage

model_message = model.invoke(prompt_value)
print('model_message >> ', model_message)
AIMessage(content="Why did the ice cream go to therapy? \n\nBecause it had too many toppings and couldn't find its cone-fidence!")

model_message >>  content='有一天,一个小男孩走进一家冰淇淋店。他看了看柜台上的各种各样的冰淇淋口味,然后决定尝试一种他从未尝过的新口味。\n\n他走到柜台前,问店员:“请问,这个新口味的冰淇淋是什么味道的呢?”\n\n店员微笑着回答:“这是我们最新推出的‘辣椒冰淇淋’,非常特别哦!”\n\n小男孩疑惑地问:“辣椒?冰淇淋?这是真的吗?”\n\n店员点点头:“是真的,你可以试试看。”\n\n小男孩有些犹豫,但还是决定尝试一下。他接过一小勺辣椒冰淇淋送进嘴里。几秒钟后,他的脸变得扭曲起来,眼泪顺着脸颊滑落。\n\n店员担心地问:“怎么样?辣吗?”\n\n小男孩用颤抖的声音回答:“不,不是辣。这是最奇怪的冰淇淋口味,它尝起来像是冰凉的火焰!”\n\n店员忍不住笑了起来:“哈哈哈,你被辣椒冰淇淋给骗了!其实,那只是普通的香草冰淇淋,但我们在上面撒了一些辣椒粉,看你的反应会不会很有趣。”\n\n小男孩虽然被捉弄了一下,但随后也加入了店员的笑声。他觉得这个冰淇淋店真是个有趣的地方,于是他决定尝试更多不同的口味,发掘更多有趣的事情。从那天起,他成了这家冰淇淋店的忠实顾客。'

如果我们的模型是一个LLM,它会输出一个字符串。

from langchain.llms import OpenAI

llm = OpenAI(model="gpt-3.5-turbo-instruct")
llm_message = llm.invoke(prompt_value)
print('llm_message >> ', llm_message)
'\n\nRobot: Why did the ice cream go to therapy? Because it had a rocky road.'

llm_message >>  

有一天,一个小女孩去买冰淇淋,店员问她想要什么口味的冰淇淋,她说:“我想要巧克力和香草混合的冰淇淋。”店员回答说:“抱歉,我们没有这种口味的冰淇淋。”小女孩沮丧地说:“那就给我一杯巧克力冰淇淋和一杯香草冰淇淋吧,我自己混合一下!”

4. Output parser

最后,我们将我们的模型输出传递给输出解析器,它是一个BaseOutputParser,这意味着它接受字符串或BaseMessage作为输入。StrOutputParser专门将任何输入简单地转换为字符串。

output_parser_message = output_parser.invoke(model_message)
"Why did the ice cream go to therapy? \n\nBecause it had too many toppings and couldn't find its cone-fidence!"

output_parser_message >>  有一天,三个朋友去吃冰淇淋。第一个朋友点了一个巧克力口味的冰淇淋,吃了一口后突然皱起了眉头。他说:“这冰淇淋好苦啊!”
第二个朋友很好奇,也点了同样的巧克力口味冰淇淋,结果吃了一口后也皱起了眉头,说:“你说得没错,这冰淇淋怎么这么苦呢?”
第三个朋友看着两位朋友的表情,心想可能他们遇到了特别苦的冰淇淋,于是他决定尝试一下。他点了一个草莓口味的冰淇淋,吃了一口后却开心地笑了起来。他说:“哈哈,你们两个怎么这么笨呀!你们点的是巧克力口味的冰淇淋,当然会苦啦!我点的是草莓口味的,怎么可能会苦呢?”

5. Entire Pipeline 整个流程

在这里插入图片描述

要跟着这些步骤走:

  1. 我们以用户输入的所需主题为{"topic": "ice cream"}
  2. 提示组件接受用户输入,然后使用主题构建提示后生成PromptValue
  3. 模型组件接受生成的提示,并传递给OpenAI LLM模型进行评估。模型生成的输出是一个ChatMessage对象。
  4. 最后,output_parser组件接受ChatMessage,并将其转换为Python字符串,然后从调用方法中返回。

请注意,如果你对任何组件的输出感到好奇,你可以随时测试一个较小版本的链条,比如 promptprompt | model,以查看中间结果:

input = {"topic": "ice cream"}

prompt.invoke(input)
# > ChatPromptValue(messages=[HumanMessage(content='tell me a short joke about ice cream')])

(prompt | model).invoke(input)
# > AIMessage(content="Why did the ice cream go to therapy?\nBecause it had too many toppings and couldn't cone-trol itself!")

代码

https://github.com/zgpeace/pets-name-langchain/tree/develop

参考

https://python.langchain.com/docs/expression_language/get_started

文章来源:https://blog.csdn.net/zgpeace/article/details/135200043
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。