我的AI学习 langchain之三(LCEL)

LangChain Expression Language(LCEL)是一种声明式语言,可轻松组合不同的调用顺序构成 Chain
LCEL 的一些亮点包括:

  1. 流支持
  2. 异步支持
  3. 化的并行执行
  4. 重试和回退
  5. 访问中间结果
  6. 输入和输出模式
  7. 无缝 LangSmith 跟踪集成
  8. 缝 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/

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值