Langchain为LLMs提供了可选的缓存层。这个很有用,原因是:

  • 如果经常向模型多次请求提问相同的内容,Caching缓存可以减少对LLM进行API调用次数来提升程序运行效率。

Caching缓存

具体实现:

  • 设置一个内存缓存(InMemoryCache)来缓存大型语言模型(LLM)的调用结果,以提高后续相同请求的处理速度。

fromlangchain.globalsimportset_llm_cache#用于设置全局的LLM缓存机制。
fromlangchain.cacheimportInMemoryCache#将缓存数据存储在内存中,而不是磁盘上
set_llm_cache(InMemoryCache()) #使用内存缓存来存储和检索LLM的调用结果。

第一次向模型进行提问:耗时较久,但是会讲提问内容加入到缓存中

fromlangchain_openaiimportOpenAI
fromlangchain_openaiimportChatOpenAI
#提示词作用到模型进行聊天记录总结
API_KEY="sk-4b79xxxx935366ebb425b3"
chat=ChatOpenAI(
    model_name="deepseek-chat",
    api_key=API_KEY,
    base_url="https://api.deepseek.com"
)

response=chat.invoke("3只鸭子几条腿?")
response.content

再次提问相同内容,直接基于缓存内容进行回复,响应速度快

response=chat.invoke("3只鸭子几条腿?")
response.content

SQLite缓存

具体实现:

设置一个SQLite缓存来缓存大型语言模型(LLM)的调用结果,以提高后续相同请求的处理速度。

fromlangchain.cacheimportSQLiteCache
set_llm_cache(SQLiteCache(database_path="./langchain.db"))

#加入问答到缓存中
response=chat.invoke("讲一个10个字的故事?")
response.content

基于缓存进行快速响应

response=chat.invoke("讲一个10个字的故事?")
response.content

输出解析器

输出解析器(Output Parser)在提示词工程中扮演着重要角色。让我们更详细地探讨它的两大功能以及为什么它与提示词模板有关系。

输出解析器的功能:

输出解析器的一个关键功能是向现有的提示词模板中添加输出指令。这些指令告诉语言模型应该如何格式化和结构化生成的输出内容。例如:

  • JSON格式"请以JSON格式输出以下信息:{ "name": "用户姓名", "age": "用户年龄" }"

  • HTML格式"请以HTML格式输出以下信息:<div>用户姓名: 用户名</div><div>用户年龄: 用户年龄</div>"

  • 纯文本格式"请以纯文本格式输出以下信息:姓名: 用户名, 年龄: 用户年龄"

通过添加这些输出指令,输出解析器确保模型按照指定的格式生成输出,而不是仅仅返回原始数据。

预设的 LangChain 输出解析器

LangChain 提供了一堆预设的输出解析器,这些解析器真的超实用,包括:

  1. BooleanOutputParser:这个解析器专门用于解析布尔值(即对错、真假)的输出。例如,当模型输出是 True 或 False 时,该解析器可以准确识别和处理。

  2. CommaSeparatedListOutputParser:此解析器用于解析以逗号分隔的列表输出。比如,当模型返回一个由逗号分隔的字符串时,这个解析器可以将其转换为一个列表。

  3. DatetimeOutputParser:该解析器用于处理日期和时间的输出。它能够将模型生成的日期时间字符串解析为标准的日期时间格式,方便后续处理。

  4. EnumOutputParser:枚举类型的输出可以通过这个解析器来处理。枚举类型通常是指有限个选项的类型,比如星期几、颜色等,这个解析器能够准确识别并转换这些输出。

  5. ListOutputParser:当输出是一个列表时,无论是什么类型的列表,都可以使用这个解析器进行解析。它能将模型生成的列表字符串转换为实际的列表对象。

  6. PydanticOutputParser:如果你的输出需要符合 Pydantic 的要求(Pydantic 是一个用于数据验证和转换的库),那么这个解析器就能派上用场。它可以确保输出数据符合预定义的数据模型和验证规则。

  7. StructuredOutputParser:对于具有特定结构的输出,这个解析器可以大显身手。它能够处理复杂的结构,并将模型生成的结构化数据解析为易于使用的格式。

CommaSeparatedListOutputParser列表输出解析器示例

fromlangchain_openaiimportChatOpenAI
fromlangchain.output_parsersimportCommaSeparatedListOutputParser
fromlangchain.promptsimportPromptTemplate
#构造列表解析器
output_parser=CommaSeparatedListOutputParser()
#返回解析器的解析格式
output_parser.get_format_instructions()

注意:所有解析器的解析格式都是英文的,上述列表解析器解析格式的英文翻译是:您的响应应该是逗号分隔的值列表,例如:foo,bar,bazfoo,bar,baz`。也就是通过解析器的该种解析格式作为提示词的部分内容,约束模型按照指定格式进行内容的输出。

  • 解析器作用在PromptTemplate模版中

    #构造输入模版,这里的区别是:在输入的Prompt Template中,加入了OutPut Parse的内容
    template="""用户发起的提问:
    
    {question}
    
    {format_instructions}"""
    
    #实例化输出解析器(用于解析以逗号分隔的列表类型的输出)
    output_parser=CommaSeparatedListOutputParser()
    
    #创建提示词模版,将输出解析器的解析格式作为提示词模版的部分内容
    prompt=PromptTemplate.from_template(
        template,
        partial_variables={"format_instructions":
                           output_parser.get_format_instructions()},
    )
    
    
    #最后,使用LangChain中的`chain`的抽象,合并最终的提示、大模型实例及OutPut Parse共同执行。
    API_KEY="sk-4b79f3a3xxxa1935366ebb425b3"
    
    model=ChatOpenAI(model="deepseek-chat",
                       openai_api_key=API_KEY,
                       openai_api_base="https://api.deepseek.com")
    
    chain=prompt|model|output_parser
    output=chain.invoke({"question": "列出北京的三个景点"})
    output
    • LCEL: LangChain Execution Language(LangChain 表达语⾔)是⼀种声明性的⽅式来链接 LangChain 组件(工作流)。 

  • 解析器作用在ChatPromptTemplate模版中

    fromlangchain_openaiimportChatOpenAI
    fromlangchain.output_parsersimportCommaSeparatedListOutputParser
    fromlangchain.promptsimportChatPromptTemplate
    
    #构建提示词模版
    prompt=ChatPromptTemplate.from_messages([
        ("system", "{parser_instructions}"),
        ("human", "列出{cityName}的{viewPointNum}个著名景点。")
    ])
    
    #构建输出解析器并获取解析格式
    output_parser=CommaSeparatedListOutputParser()
    parser_instructions=output_parser.get_format_instructions()
    
    #动态补充提示词内容
    final_prompt=prompt.invoke({"cityName": "南京", "viewPointNum": 3, 
                                  "parser_instructions": parser_instructions})
    
    #最后,使用LangChain中的`chain`的抽象,合并最终的提示、大模型实例及OutPut Parse共同执行。
    API_KEY="sk-4b79f3axxx1935366ebb425b3"
    model=ChatOpenAI(model="deepseek-chat",
                       openai_api_key=API_KEY,
                       openai_api_base="https://api.deepseek.com")
    
    
    response=model.invoke(final_prompt)
    ret=output_parser.invoke(response)
    print(ret)

DatetimeOutputParser时间输出解析器示例

fromlangchain.output_parsersimportDatetimeOutputParser#日期输出解析器
fromlangchain.promptsimportPromptTemplate

#制定输出解析器
output_parser=DatetimeOutputParser()

#制定提示词模版
template="""回答用户的问题:
{question}

{format_instructions}"""

#时间解析器的解析格式
format_instructions=output_parser.get_format_instructions()

#补充提示词模版
prompt=PromptTemplate.from_template(
    template,
    partial_variables={"format_instructions":format_instructions}
)

API_KEY="sk-4b79f3axxx1935366ebb425b3"
model=ChatOpenAI(model="deepseek-chat",
                   openai_api_key=API_KEY,
                   openai_api_base="https://api.deepseek.com")

chain=prompt|model|output_parser
output=chain.invoke("周杰伦是什么时候出道的?")
output

EnumOutputParser枚举输出解析器示例

fromlangchain.output_parsers.enumimportEnumOutputParser
fromenumimportEnum

#定义枚举类型
classColors(Enum):
    RED="红色"
    BROWN="棕色"
    BLACK="黑色"
    WHITE="白色"
    YELLOW="黄色"
    
#制定输出解析器
parse=EnumOutputParser(enum=Colors)

#制定提示词模版
promptTemplate=PromptTemplate.from_template(
    """{person}的皮肤主要是什么颜色?
    
    {instructions}"""
)
#解析器的解析格式:原本解析器的英文解析格式会报错
# instructions = parse.get_format_instructions() 
instructions="响应结果请选择以下选项之一:红色、棕色、黑色、白色和黄色。"
#提示词部分补充
prompt=promptTemplate.partial(instructions=instructions)

chain=prompt|model|parse
chain.invoke({"person":"亚洲人"})

注意:直接使用输出解析器原始的英文的解析格式作用到提示词中可能由于中英文掺杂和中英文语义的区别导致模型报错,因此,可以适当将输出解析器的解析格式手动翻译成英文后再用!

Pydantic JSON 输出解析器

JSON输出解析器允许用户指定任意JSON架构并查询LLMs以获取符合该框架的输出。

fromlangchain_openaiimportChatOpenAI
fromlangchain_core.output_parsersimportJsonOutputParser
fromlangchain_core.pydantic_v1importBaseModel,Field
fromlangchain.promptsimportPromptTemplate
fromtypingimportList

#定义JSON结构
classBook(BaseModel):
    title:str=Field(description="书名")
    author:str=Field(description="作者")
    description:str=Field(description="书的简介")
    beLike:List[str] =Field(description="相关书籍的名称")
    
query="请给我介绍下中国历史的经典书籍"

parser=JsonOutputParser(pydantic_object=Book)

format_instructions=parser.get_format_instructions()
# format_instructions = '''输出应格式化为符合以下JSON模式的JSON实例。JSON结构如下:{"title":"标题","author":"作者","description":"书的简介"}'''
prompt=PromptTemplate(
    template="{format_instructions}\n{query}\n",
    input_variables=["query"],
    partial_variables={"format_instructions":format_instructions}
)

chain=prompt|model|parser
chain.invoke({"query":query})

xml输出解析器

fromlangchain_openaiimportChatOpenAI
fromlangchain_core.promptsimportPromptTemplate
fromlangchain_core.output_parsersimportXMLOutputParser

API_KEY="sk-4b79f3axxx935366ebb425b3"
model=ChatOpenAI(
    model_name="deepseek-chat",
    api_key=API_KEY,
    base_url="https://api.deepseek.com"
)

# 还有⼀个⽤于提示语⾔模型填充数据结构的查询意图。
actor_query="⽣成周星驰的简化电影作品列表,按照最新的时间降序"

# 设置解析器 + 将指令注⼊提示模板。
parser=XMLOutputParser()
prompt=PromptTemplate(
    template="回答⽤户的查询。\n{format_instructions}\n{query}\n",
    input_variables=["query"],
    partial_variables={"format_instructions": parser.get_format_instructions()},
)
# print(parser.get_format_instructions())

chain=prompt|model
response=chain.invoke({"query": actor_query})
xml_output=parser.parse(response.content)
print(response.content)

自定义输出解析器

在某些情况下,我们可以实现自定义解析器以将模型输出内容构造成自定义的格式。

fromtypingimportIterator
fromlangchain_core.messagesimportAIMessage,AIMessageChunk

#自定义输出解析器
defparse(ai_message:AIMessage)->str:
    #函数参数就是模型的输出。
    #swapcase表示将模型输出内容大小写进行相互转换后进行返回
    returnai_message.content.swapcase()

chain=model|parse
response=chain.invoke("are you ok?")
response
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐