Jean's Blog

一个专注软件测试开发技术的个人博客

0%

LangChain组件ChatModels(磨平不同LLM的差异)

ChatModels & LLMs

image-20250829091634751

LangChain中的大模型组件主要分为ChatModels和LLMs两类,ChatModels支持OpenAI和LangChain两种消息格式、工具调用、结构化输出及多模态处理,适用于现代对话场景;而LLMs仅支持字符串输入输出,功能较单一,已逐渐被弃用。此外,LongChain 0.3版本后对依赖包进行了拆分,分为官方合作包(如ChatOpenAI)和社区开发包(如LangChain Community),前者由官方维护,适配主流模型,后者由社区贡献,灵活性较高但维护性较差。实际开发中推荐使用ChatModels和官方合作包以确保兼容性和稳定性。

  • ChatModels具备工具调用能力(Tool Call / Function Call)并支持结构化输出如JSON/XML
  • ChatModels支持多模态输入输出,包括文本、音频、图像等
  • LLMs是早期版本遗留下来的模式,目前已逐渐被Chat Modules取代
  • 通过函数名前缀判断模块类型:Chat开头的是ChatModels,LLM结尾的是llms

LangChain包相关的:

大模型的接入示例

OpenAI接入

1
2
3
4
5
6
7
8
9
10
import os
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
model="gpt-4",
temperature=0,
api_key=os.environ.get("OPENAI_API_KEY"),
base_url=os.environ.get("OPENAI_API_BASE"),
)
llm.invoke("介绍下你自己")

DeepSeek接入

1
2
3
4
5
6
7
8
9
10
import os
from langchain_deepseek import ChatDeepSeek

llm = ChatDeepSeek(
model="Pro/deepseek-ai/DeepSeek-R1",
temperature=0,
api_key=os.environ.get("DEEPSEEK_API_KEY"),
api_base=os.environ.get("DEEPSEEK_API_BASE"),
)
llm.invoke("介绍下自己")

Anthropic接入

1
2
3
4
5
6
7
8
9
import os
from langchain_anthropic import ChatAnthropic

model = ChatAnthropic(
model='claude-3-5-sonnet-latest',
api_key=os.environ.get("ANTHROPIC_API_KEY"),
base_url=os.environ.get("ANTHROPIC_BASE_URL"),
)
model.invoke("介绍下自己")

标准参数、事件、与输入输出

学习了大模型组件的标准参数和事件,包括模型名称、随机度(temperature)、超时时间、输出长度限制等配置,以及调用模型的主要方法如Invoke、Stream、Batch和异步流式输出。通过合理设置这些参数和使用不同事件,可以提升应用的交互体验和功能实现。

标准参数

补全参数 (Completion Params)

这些参数主要用于控制生成文本的特性。

  • model: 要使用的 OpenAI 模型的名称,类型为 str
  • temperature: 采样温度,类型为 float。该值越高,生成文本的随机性越强;反之,值越低,生成文本的确定性越强。
  • max_tokens: 要生成的最大 token 数量,类型为可选的 int。这决定了生成文本的长度上限。
  • logprobs: 是否返回每个生成 token 的对数概率,类型为可选的 bool。这对于分析模型预测的置信度很有用。
  • stream_options: 配置流式输出的选项,类型为 Dict。例如,可以设置 {"include_usage": True} 来在流式传输时返回 token 使用情况。
  • use_responses_api: 是否使用 responses API,类型为可选的 bool
  • stop:指定停止字符

客户端参数 (Client Params)

这些参数主要用于配置客户端与 OpenAI API 的交互方式。

  • timeout: 请求的超时时间,类型为 Union[float, Tuple[float, float], Any, None]。可以是一个浮点数表示总超时时间,也可以是一个元组来分别指定连接和读取超时时间。
  • max_retries: 最大重试次数,类型为可选的 int。当请求失败时,客户端会尝试重新发送请求,此参数决定了最大重试次数。
  • api_key: OpenAI API 密钥,类型为可选的 str。如果未在此处传入,将从环境变量 OPENAI_API_KEY 中读取。
  • base_url: API 请求的基础 URL,类型为可选的 str。只有在使用代理或服务模拟器时才需要指定。
  • organization: OpenAI 组织 ID,类型为可选的 str。如果未传入,将从环境变量 OPENAI_ORG_ID 中读取。
  • rater_limiter:请求速率限制

注意:

  • 标准参数只对本身API开发了相关参数的模型有用,比如有的模型本身没有指定的max_token,则其在LangChain中也无效
  • 标准参数仅在官方合作包中强制要求,社区开发包不做强制要求

根据标准参数,大模型初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import os
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
model="gpt-4",
temperature=0.4,
api_key=os.environ.get("OPENAI_API_KEY"),
base_url=os.environ.get("OPENAI_API_BASE"),
timeout=30,
max_tokens=200,
stop="我", # 停止字符,遇到“我”则会停止输出
max_retries = 3
)
llm.invoke("介绍下你自己")

标准事件

  • invoke:模型主要调用方法,输入list,输出list
  • stream:流式输出方法
  • batch:批量模型请求方法
  • bind_tools:在模型执行的时候绑定工具
  • with_structured_output:给予invoke的结构化输出

其他有用事件

  • ainvoke:异步调用模型方法
  • astream:异步流式输出
  • abatch:异步的批量处理
  • astream_events:异步流事件,支持更细粒度的控制
  • with_retry:调用失败时才重试
  • with_fallback:失败恢复事件
  • configurble_fields:模型运行时的运行参数,适用于复杂的应用开发场景

标准事件,代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 定义模型
from langchain_openai import ChatOpenAI
import os
import asyncio

llm = ChatOpenAI(
model="gpt-4",
temperature=0,
api_key=os.environ.get("OPENAI_API_KEY"),
base_url=os.environ.get("OPENAI_API_BASE"),
)
question = "langchain是什么?"

# invoke事件
llm.invoke(question)

# stream事件
for chunk in llm.stream(question):
print(chunk.content+"|")

# batch事件
llm.batch(["langchain作者是谁?", "Langchain的竞品有哪些?"])

# 异步事件流
async for event in llm.astream_events("介绍下LangChain", version="v2"):
print(f"event={event['event']} | name={event['name']} | data={event['data']}")

标准事件之结构化输出 - with_structured_output,代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 标准事件之结构化输出 - with_structured_output
# 影响LLM的输出

from typing import Optional
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
import os

llm = ChatOpenAI(
model="gpt-4",
temperature=0,
api_key=os.environ.get("OPENAI_API_KEY"),
base_url=os.environ.get("OPENAI_API_BASE"),
)

class Joke(BaseModel):
"""Joke to tell user."""
setup: str = Field(description="The setup of the joke")
punchline: str = Field(description="The punchline to the joke")
rating: Optional[int] = Field(
default=None, description="How funny the joke is, from 1 to 10"
)
structured_llm = llm.with_structured_output(Joke)
structured_llm.invoke("给我讲一个关于程序员的笑话")

数据通信的格式

OpenAI Messages

  • SystemMessage:用于传导对话的内容
  • HumanMessage:用户输入的内容
  • AIMessage:模型响应的内容
  • 多模型

LangChain Messages

  • SystemMessage:系统角色
  • HumanMessage:用户角色
  • AIMessage:应用助理角色
  • AIMessageChunk:应用助理流式输出
  • ToolMessage:工具角色

AIMessage

AI返回的数据

属性 标准化 描述
content 原生 通常为字符串,但也可以时内容块列表
tool_calls 标准化 与消息相关的工具调用
invalid_tool_calls 标准化 工具调用与消息相关的解析错误
usage_metadata 标准化 元数据(输入输出token数,总计token数等)
id 标准化 消息唯一标识
response_metadata 原生 响应元数据(响应头、token计数等)

注意:不同的大模型提供的内容属性并不相同目前行业暂无统一标准

几款主流大模型响应数据的字段对比

大模型的厂商都是提供详细的接口调用的详细说明,会有字段详细的说了,如果需要多不同大模型的协作,因此查看文档后,需要处理统一格式。

字段类别 字段名 DeepSeek OpenAI (ChatGPT) 阿里云 (Qwen) Anthropic (Claude)
基本结构 响应结构 status, code, message, data object, choices, usage object, choices, usage 与OpenAI类似
唯一ID id (在data内) id id id
生成内容 回复内容 generated_text (在data内) choices[index].message.content choices[index].message.content content (位于不同结构中)
停止原因 未明确提及 choices[index].finish_reason choices[index].finish_reason stop_reason
角色 未明确提及 choices[index].message.role (assistant) choices[index].message.role (assistant) role
使用统计 Token消耗 token_count (在data内) usage.prompt_tokens, usage.completion_tokens, usage.total_tokens usage.prompt_tokens, usage.completion_tokens, usage.total_tokens 需在请求中设置 extra_parameters 来获取
模型信息 模型名称 在请求中指定 model model model
系统指纹 未明确提及 system_fingerprint system_fingerprint (常为null) 未明确提及
时间戳 timestamp (ISO8601) created (Unix时间戳) created (Unix时间戳) 未明确提及
高级功能 工具调用 未明确提及 tool_calls

模型上下文窗口与token

大模型的上下文窗口是指模型一次可处理的最大文本长度,受限于计算复杂度、硬件显存和训练数据长度。窗口过长会导致内存和计算需求激增,并可能因注意力衰减影响长文效果。解决方式包括引入外挂记忆(如REG)、滑动窗口技术及新架构探索。Token是模型处理的基本单位,其信息密度高于字符,且不同模型支持的窗口长度不一,应用时需注意控制输入输出长度以避免溢出问题。

什么是上下文窗口

是大模型一次最多可以处理上下文的长度,根据模型有关,跟以下相关:

  • 计算复杂度:Transformer架构自注意力机制计算复杂度O(n²),其中n是序列长度,当n增长时,内存和计算需求呈平方增长
  • 硬件限制:GPU显存有限,处理长序列需要更多显存,序列越长模型响应时间越长
  • 训练数据限制:预训练数据大多为短文本、长文本比较少,模型难以学习长距离依赖关系
  • 注意衰减:随着序列长度增加,模型会对早期信息注意力下降,从而造成遗忘和长文质量不佳现象

模型的token

  • token事大模型处理信息的基本单位,将文本转化为机器更容易处理的形式,token并非等同于字符或单词,1token不等于1汉子
  • token可以是一个字一个词一句话一部分图片信息
  • token具有更高的语言浓缩能力,比原始字符更高效地表达语义和上下文关系
  • 给机器读的语言
  • 不同模型对token的定义和切分方式有所不同,例如OpenAI中的一个token约等于4个英文字符,3/4个单词
  • 应用中需要注意token不能超出模型上下文窗口的限制

token的监控与追踪

  • 大多数模型支持token消耗的追踪,用于统计费用及优化性能。
  • LangChain中可通过usage字段获取详细的token用量信息,包括输入、输出token数。
  • 不同平台(如DeepSeek、OpenAI)的token元数据字段名称略有差异,但用途一致。
  • 支持流式输出时的token追踪,尤其在OpenAI API中可以通过stream usage开启。

速率限制与缓存机制

在实际应用中,很多模型如DeepSeek对其API有速率限制,主要是因为用户量增长快导致API压力大,为防止服务不可用,各家都会进行限制。以OpenAI为例,不同用户类型和模型有不同的速率限制标准,如免费用户每分钟只能请求三次,付费用户则相对宽松。为应对速率限制,通常会引入缓存机制减少模型调用频率,同时也可以通过设置速率控制参数(如RateLimiter)来避免超出限制,从而提升系统稳定性和用户体验。

账户类型 Text & Embedding(文本和嵌入) Chat (聊天对话) Edit (编辑) Image (图像) Audio (音频)
Free trial users(免费试用用户) 3 RPM, 150,000 TPM 3 RPM, 40,000 TPM 3 RPM, 150,000 TPM 5 images / min 3 RPM
按需付费用户 (前 48 小时) 60 RPM, 250,000 TPM 60 RPM, 60,000 TPM 20 RPM, 150,000 TPM 50 images / min 50 RPM
按量付费用户 (48 小时后) 3,500 RPM, 350,000 TPM 3,500 RPM, 90,000 TPM 20 RPM, 150,000 TPM 50 images / min 50 RPM

备注:

  • RPM (Requests Per Minute):每分钟请求数。
  • TPM (Tokens Per Minute):每分钟 Token 数。
graph TD
A[用户问题] --> B[是否相同]
    B --> C(缓存层)
    B --> D(LLM)

缓存层:

  • 长期缓存
  • 短期缓存

速率限制示例代码

langchain中的InMemoryRateLimiter(写入内存)只能限制单位时间内的请求数量, 无法处理根据请求大小来限制的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import os
from langchain_openai import ChatOpenAI
from langchain_core.rate_limiters import InMemoryRateLimiter


rate_limiter = InMemoryRateLimiter(
requests_per_second=1, # 每1秒请求一次
check_every_n_seconds=0.1, # 每100毫秒检查一次是否允许
max_bucket_size=10, # 控制最大突发大小
)

api_base = os.getenv("OPENAI_API_BASE")
api_key = os.getenv("OPENAI_API_KEY")

llm = ChatOpenAI(
temperature=0.0,
base_url=api_base,
api_key=api_key,
rate_limiter=rate_limiter #请求速率限制
)

大模型工具调用原理

大模型工具调用是指在应用开发中,让模型具备调用外部工具的能力,区别于普通使用方式。通过绑定工具(如数据库查询、天气API等),模型可根据用户问题判断是否需要调用工具,并生成结构化数据请求工具执行,获取实时信息或处理复杂任务(如数学运算),从而增强模型的实用性与准确性。工具调用扩展了模型的功能,使其能结合外部资源提供更精准的回答。

  • 创建工具(如数据库工具)
  • 将工具绑定到模型
  • 模型判断某个输入问题需要调用工具
  • 工具调用生成结构化数据
  • 使用工具(查询数据库)
  • 得到工具使用的结果(数据结果)
  • 返回给大模型增强回答

image-20250829144113686

  • 工具调用允许大模型通过调用工具来响应提示词
  • 事实是模型只是生成工具参数,并不直接运行
  • 本质上是模型生成的一段特定的结构化数据
  • 并不是所有的模型都支持工具调用

绑定工具的代码示例

两种方式:

  1. 大模型直接绑定

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    import os
    from pydantic import BaseModel, Field
    from langchain_openai import ChatOpenAI

    api_base = os.getenv("OPENAI_API_BASE")
    api_key = os.getenv("OPENAI_API_KEY")

    llm = ChatOpenAI(
    temperature=0.0,
    base_url=api_base,
    api_key=api_key
    )

    #加法工具
    class add(BaseModel):
    """Add two integers."""

    a: int = Field(..., description="First integer")
    b: int = Field(..., description="Second integer")

    #乘法工具
    class multiply(BaseModel):
    """Multiply two integers."""

    a: int = Field(..., description="First integer")
    b: int = Field(..., description="Second integer")

    tools = [add,multiply] # 一个模型可以绑定多个工具的
    llm_with_tools = llm.bind_tools(tools)
    query="3乘以12是多少?"
    llm_with_tools.invoke(query).tool_calls # 输出大模型调用的工具
  1. 使用@tool装饰器,注意:函数一定要有注释,这个会作为定义工具的描述

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    import os
    from langchain_core.tools import tool
    from langchain_openai import ChatOpenAI

    api_base = os.getenv("OPENAI_API_BASE")
    api_key = os.getenv("OPENAI_API_KEY")

    llm = ChatOpenAI(
    temperature=0.0,
    base_url=api_base,
    api_key=api_key
    )

    @tool
    def multiply(a:int,b:int) -> int:
    """Multiply two numbers."""
    return a*b

    print(multiply.name)
    print(multiply.description)
    print(multiply.args)

    print("********************************************")
    tools = [multiply]
    llm_with_tools = llm.bind_tools(tools)
    query="3乘以12是多少?"
    llm_with_tools.invoke(query).tool_calls

LangChain ModelsIO OutputParsers

LangChain已经可以轻松实现帮用户拿到大语言模型的输出,然而不难发现,前文介绍的模型调用,显示返回的内容通常是一个类(class)实例,其中包含了content以及其他一些额外的参数。

对于模型调用者来说,可能只关心content的内容,也就是模型对输入内容的回答,或者希望得到一个可操作的数据结构,比如JSON格式的数据。

OutputParsers的优势

LangChain设计的初衷之一,旨在让用户更便捷地使用大模型,所以为了解决输出内容格式化的问题。

通过使用LangChain提供的解析器,用户可以更轻松地获取模型的输出,并直接处理或操作所需的内容,而无需进行额外的转换或处理。

解析器类型

根据业务需求,开发者通常需要大模型返回一个结构化的数据,方便后续的逻辑可以根据这个数据进行进一步的处理。

然而不同的输入结果可能需要相对应的解析器来做处理,LangChain同样提供了几种常见的解析器类型:

  • String解析器
  • Json解析器
  • Pydantic解析器
  • 结构化输出解析器
  • OpenAI函数输出解析器

实战示例

String解析器

LangChain提供了StrOutputParser,这是一个专门用来处理模型输出内容的解析器。当模型输出的内容是字符串格式的时候,StrOutputParser能够直接返回模型输出的content字符串内容。

这使得用户无需进行复杂的数据解析操作,可以直接获取模型输出的内容字符串,从而变更方便地进行后续处理或使用,代码示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from langchain_core.messages import SystemMessage
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_openai import OpenAI

from config_info import get_config_info

# ChatGPT模型调用对象
llm = OpenAI(openai_api_key=get_config_info().get('key'),
openai_api_base=get_config_info().get('base'))


def string_parser_demo():
"""
String解析器
StrOutputParser
:return:
"""
# 提示词模版
messages = ChatPromptTemplate.from_messages([
SystemMessage(content="你是一个翻译各种语言的助手"),
HumanMessagePromptTemplate.from_template("把{poetry}的原文翻译为英文")
])
# 输出解析器,转换为字符串
parser = StrOutputParser()
# 调用链, 使用输出解析器
chain_with_parser = messages | llm | parser
# 发送请求
res = chain_with_parser.invoke({'poetry': '静夜思'})
print(res)

Json解析器

当模型输出的内容是一个JSON格式时,LangChain也提供了相应的解析器JsonOutputParser。该解析器能够根据JSON结构的内容,将其转换为Python对应的字典格式的数据,使得用户能够更方便地处理和操作模型输出的结果。代码示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# @Time: 2025/2/6 10:43
# @Author: lvjing
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI

from config_info import get_config_info

# ChatGPT模型调用对象
llm = OpenAI(openai_api_key=get_config_info().get('key'),
openai_api_base=get_config_info().get('base'))

def json_parser_demo():
"""
Json解析器
JsonOutputParser
:return:
"""
# 输出解析器,转换为Json
parser = JsonOutputParser()
# 提示词模版,输出json格式的回答
prompt = PromptTemplate(
template="根据用户输入,给出一段中文宣传语 \n{format_instructions}\n{ads}\n",
input_variables=["ads"],
partial_variables={"format_instructions": parser.get_format_instructions()}
)
# 调用链, 包含json输出解析器
chain_with_parser = prompt | llm | parser
# 发送请求
res = chain_with_parser.invoke({'ads': '音乐节'})
print(res)
print(type(res))

Pydantic解析器

LangChain还提供了对Pydantic模型的解析器:PydanticOutputParser

LangChain的Pydantic解析器可以将模型输出的内容解析为Pydantic模型所定义的数据结构。这使得用户可以更加方便的使用Pydantic的功能,例如数据验证、序列化和反序列化等,代码示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# @Time: 2025/2/6 10:43
# @Author: lvjing
from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
from pydantic import BaseModel, Field

from config_info import get_config_info

# ChatGPT模型调用对象
llm = OpenAI(openai_api_key=get_config_info().get('key'),
openai_api_base=get_config_info().get('base'))


class Translation(BaseModel):
original_str: str = Field(description="原始输入的值")
trans_str: str = Field(description="翻译后的值")


def pydantic_parser_demo():
"""
Pydantic解析器
PydanticOutputParser
:return:
"""
# 使用Pydantic输出解析器解析Translation类
parser = PydanticOutputParser(pydantic_object=Translation)
# 提示词模版,
prompt = PromptTemplate(
template="翻译用户输入的内容为英文 \n{format_instructions}\n{query}\n",
input_variables=["query"],
partial_variables={"format_instructions": parser.get_format_instructions()}
)
# 调用链
chain_with_parser = prompt | llm | parser
# 发送请求
res = chain_with_parser.invoke({'query': '赏花'})
print(res)
print(type(res))

结构化输出解析器

LangChain提供了一种自定义解析方案,即使用schema结构。用户可以根据需要定义自己的schema,并使用LangChain的StructuredOutputParser类来解析符合该schema的数据。

这种方式让用户能够更灵活地处理各种类型的模型输出数据,而无需依赖特定的数据验证库或框架。StructuredOutputParser为用户提供了一种通用的解析方式,使他们能够简单地将模型输出的数据转换为符合自定义schema的数据对象。代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# @Time: 2025/2/6 10:43
# @Author: lvjing
from langchain.output_parsers import ResponseSchema, StructuredOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI

from config_info import get_config_info

# ChatGPT模型调用对象
llm = OpenAI(openai_api_key=get_config_info().get('key'),
openai_api_base=get_config_info().get('base'))


def structured_parser_demo():
"""
结构化数据解析器
StructuredOutputParser
:return:
"""
# 定义schema对象
response_schema = [
ResponseSchema(name="slogan", description="宣传语内容"),
ResponseSchema(name="req", description="宣传语限制在10个字符内")
]
output_parser = StructuredOutputParser.from_response_schemas(response_schema)
# 提示词模版,
prompt = PromptTemplate(
template="根据用户输入的商品给出宣传语\n{format_instructions}\n{topic}\n",
input_variables=["topic"],
partial_variables={"format_instructions": output_parser.get_format_instructions()}
)
# 调用链
chain_with_parser = prompt | llm | output_parser
# 发送请求
res = chain_with_parser.invoke({'topic': '音乐节'})
print(res)
print(type(res))

OpenAI函数输出解析器

LangChain支持解析OpenAI提供的函数调用,并提供了以下四种形式来处理输出结果:

  • JsonOutputFunctionsParser:生成JSON格式的结果
  • JsonKeyOutputFunctionsParser:指定JSON中某个key对应的value
  • PydanticOutputFunctionsParser:解析Pydantic模型的结构
  • PydanticAttrOutputFunctionsParser:直接输出模型中某个参数的值

Json格式

JsonOutputFunctionsParser 和 JsonKeyOutputFunctionsParser(key_name=”ad”)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# @Time: 2025/2/6 10:43
# @Author: lvjing
from langchain_core.output_parsers.openai_functions import JsonOutputFunctionsParser, JsonKeyOutputFunctionsParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

from config_info import get_config_info

model = ChatOpenAI(openai_api_key=get_config_info().get('key'),
openai_api_base=get_config_info().get('base'))


def openai_json_demo():
"""
OpenAI函数输出解析器--JSON格式
:return:
"""
# 自定函数
functions = [
{
"name": "advertisement",
"description": "一段广告词",
"parameters": {
"type": "object",
"properties": {
"goods": {
"type": "string", "description": "要进行广告的产品"
},
"ad": {
"type": "string", "description": "广告词"
}
},
"required": ["goods", "ad"]
}
}
]
# 提示词模版
prompt = ChatPromptTemplate.from_template("给出一个关于{goods}的广告宣传语")
# 创建调用链,包含输出解析器
chain_json_with_parser = prompt | model.bind(function_call={"name": "advertisement"},
functions=functions) | JsonOutputFunctionsParser()
res = chain_json_with_parser.invoke({"goods": "冰淇淋"})
print(res)
print(type(res))

print("================================")

chain_json_key_with_parser = prompt | model.bind(function_call={"name": "advertisement"},
functions=functions) | JsonKeyOutputFunctionsParser(key_name="ad")
res_key = chain_json_key_with_parser.invoke({"goods": "冰淇淋"})
print(res_key)
print(type(res_key))

Pydantic模型

PydanticOutputFunctionsParser(pydantic_schema=Advertisement) 和 PydanticAttrOutputFunctionsParser(pydantic_schema=Advertisement, attr_name=”ads”)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# @Time: 2025/2/6 10:43
# @Author: lvjing
from langchain_core.output_parsers.openai_functions import PydanticOutputFunctionsParser, \
PydanticAttrOutputFunctionsParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.utils.function_calling import convert_to_openai_function
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field

from config_info import get_config_info

model = ChatOpenAI(openai_api_key=get_config_info().get('key'),
openai_api_base=get_config_info().get('base'))


class Advertisement(BaseModel):
"""
Pydantic模型
"""
goods: str = Field(description="物品")
ads: str = Field(description="宣传语")


def pydantic_json_demo():
"""
OpenAI函数输出解析器--Pydantic模型
:return:
"""
# 定义解析器
parser = PydanticOutputFunctionsParser(pydantic_schema=Advertisement)
# 创建调用函数(转换为列表)
openai_functions = [convert_to_openai_function(Advertisement)]
# 提示词模版
prompt = ChatPromptTemplate.from_template("给出一个关于{goods}的广告宣传语")
# 创建调用链
chain_pydantic_parser = prompt | model.bind(functions=openai_functions) | parser
res = chain_pydantic_parser.invoke({"goods": "饮料"})
print(res)
print(type(res))

print("================================")

# 定义解析器
parser_attr = PydanticAttrOutputFunctionsParser(pydantic_schema=Advertisement, attr_name="ads")
# 创建调用链
chain_pydantic_parser_attr = prompt | model.bind(functions=openai_functions) | parser_attr
res_attr = chain_pydantic_parser_attr.invoke({"goods": "饮料"})
print(res_attr)
print(type(res_attr))