LangChain Expression Language(LCEL)是一种声明式语言,可轻松组合不同的调用顺序构成 Chain
LCEL 的一些亮点包括:
- 流支持
- 异步支持
- 化的并行执行
- 重试和回退
- 访问中间结果
- 输入和输出模式
- 无缝 LangSmith 跟踪集成
- 缝 LangServe 部署集成
原文:https://python.langchain.com/docs/expression_language/
1. Pipeline 式调用 PromptTemplate, LLM 和 OutputParser
用到的命名空间
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from pydantic import BaseModel, Field, validator
from typing import List, Dict, Optional
from enum import Enum
import json
# 输出结构
class SortEnum(str, Enum):
data = 'data'
price = 'price'
class OrderingEnum(str, Enum):
ascend = 'ascend'
descend = 'descend'
class Semantics(BaseModel):
name: Optional[str] = Field(description="流量包名称", default=None)
price_lower: Optional[int] = Field(description="价格下限", default=None)
price_upper: Optional[int] = Field(description="价格上限", default=None)
data_lower: Optional[int] = Field(description="流量下限", default=None)
data_upper: Optional[int] = Field(description="流量上限", default=None)
sort_by: Optional[SortEnum] = Field(description="按价格或流量排序", default=None)
ordering: Optional[OrderingEnum] = Field(description="升序或降序排列", default=None)
# Prompt 模板
prompt = ChatPromptTemplate.from_messages(
[
("system", "你是一个语义解析器。你的任务是将用户的输入解析成JSON表示。不要回答用户的问题。"),
("human", "{text}"),
]
)
# 模型
llm = ChatOpenAI(model="gpt-4o", temperature=0)
structured_llm = llm.with_structured_output(Semantics)
# LCEL 表达式
runnable = ({"text": RunnablePassthrough()} | prompt | structured_llm)
# 直接运行
ret = runnable.invoke("不超过100元的流量大的套餐有哪些")
print( json.dumps( ret.dict(), indent = 4, ensure_ascii=False))
上述LCEF语法是runnable = ({“text”: RunnablePassthrough()} | prompt | structured_llm),就是执行规则,以"|"分开的顺序.
invoke则是执行这个步骤.其中invoke中的文本给到模版中的text,其中Prompt,将解析成按Semantics的描述
流式输出
下面的代码是把对话模版修改PromptTemplate,然后再LEF语法最后增加个按流式输出的对象StrOutputParser(), 代码如下
prompt = PromptTemplate.from_template("讲个关于{topic}的笑话")
runnable = ( {"topic": RunnablePassthrough()} | prompt | llm | StrOutputParser() )
注意:在当前的文档中 LCEL 产生的对象,被叫做 runnable 或 chain
LCEL 的价值请参考https://python.langchain.com/v0.1/docs/expression_language/why/
2. 用 LCEL 实现 RAG
步骤,文档加载->切割文本片段->灌入检索引擎->封装检索接口->Prompt -> LLM -> 回复
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain_community.document_loaders import PyMuPDFLoader
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough
# 加载文档
loader = PyMuPDFLoader("llama2.pdf")
pages = loader.load_and_split()
# 文档切分
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=300,
chunk_overlap=100,
length_function=len,
add_start_index=True,
)
texts = text_splitter.create_documents(
[page.page_content for page in pages[:4]]
)
# 灌库
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
db = FAISS.from_documents(texts, embeddings)
# 检索 top-2 结果
retriever = db.as_retriever(search_kwargs={"k": 2})
# Prompt模板
template = """Answer the question based only on the following context:
{context}
Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
# 模型
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# Chain
rag_chain = ({"question": RunnablePassthrough(), "context": retriever} | prompt | llm | StrOutputParser() )
ret = rag_chain.invoke("Llama 2有多少参数")
print(ret)
模型配置,可以配置多个模型,然后调用时根据名称选择执行的模型,
from langchain_core.runnables.utils import ConfigurableField
from langchain_openai import ChatOpenAI
from langchain_community.chat_models import QianfanChatEndpoint
from langchain.prompts import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
)
from langchain.schema import HumanMessage
import os
# 模型1
ernie_model = QianfanChatEndpoint(
qianfan_ak=os.getenv('ERNIE_CLIENT_ID'),
qianfan_sk=os.getenv('ERNIE_CLIENT_SECRET')
)
# 模型2
gpt_model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 通过 configurable_alternatives 按指定字段选择模型
model = gpt_model.configurable_alternatives(
ConfigurableField(id="llm"),
default_key="gpt",
ernie=ernie_model,
# claude=claude_model,
)
# Prompt 模板
prompt = ChatPromptTemplate.from_messages(
[
HumanMessagePromptTemplate.from_template("{query}"),
]
)
# LCEL
chain = ({"query": RunnablePassthrough()}| prompt| model| StrOutputParser())
# 运行时指定模型 "gpt" or "ernie"
ret = chain.with_config(configurable={"llm": "gpt"}).invoke("请自我介绍")
print(ret)
稍微讲解一下:
我们生成了2个大模型对象,千帆和gpt, 下面代码是模型配置,如下,可以先猜测一下什么意思
model = gpt_model.configurable_alternatives(
ConfigurableField(id=“llm”),
default_key=“gpt”,
ernie=gpt_model,
# claude=claude_model,
)
意思是gpt_model模型的默认名叫gpt, ConfigurableField是给model起个名称.,最后代码{“llm”: “gpt”}的意思是大模型执行gpt,模型,
当然还可以配置{“llm”: “ernie”}意思是执行千帆模型
更多的例子请看https://python.langchain.com/v0.2/docs/how_to/lcel_cheatsheet/

1115

被折叠的 条评论
为什么被折叠?



