本文基于Python 1.13.x和LangChain 1.3.13,并采用DeekSeep大模型,介绍LangChain提示词工程的实现。
pip install langchain==1.3.13
pip install langchain-openai
langchain-openai底层也是对openai官方OpenAI Python API的封装,也可以直接用官方OpenAI Python,但是没有必要
类似的其他语言和框架的提示词工程实现案例,可以移步:
1.对话
一个基于init_chat_model的简单的对话实现
model大模型名称model_provider采用协议api_keyAPI_KEYbase_url接口地址temperature温度,越高内容越随机,越低,内容越确定max_tokens生成内容的最大token数timeout请求超时时间max_retries最大重试次数
上述这些参数,可能对某些大语言模型无效,仅对于langchain官方提供的集成包例如langchain-openai,langchain-anthropic等有效,对于langchain-community下定义的第三方模型可能无效
from langchain.chat_models import init_chat_model
import os
llm = init_chat_model(
model = 'deepseek-chat',
model_provider = 'openai',
api_key = os.getenv('DSKEY'),
base_url = 'https://api.deepseek.com'
)
msg = llm.invoke('你是谁')
print(msg)
model.invoke()返回的是一个AIMessage对象,包括以下常见内容
type描述是哪个类型的消息:user/ai/system/toolcontent大模型的输出,一般是字符串,多模态模型可能是其他内容name当消息类型相同,对消息进行区分,不是所有模型都支持response_metadataai消息才会包含的属性,附加元数据,不同模型内容也是不一样的tool_callsai消息才会包含的属性,当大模型决定调用某个工具时,就会包含,每个元素是一个字典,包含工具名name,参数args,工具唯一标识id等
可以通过llm.stream返回的迭代器对象Iterator[AIMessageChunk],得到实时流式返回的输出,打印追加
from langchain.chat_models import init_chat_model
import os
llm = init_chat_model(
model = 'deepseek-chat',
model_provider = 'openai',
api_key = os.getenv('DSKEY'),
base_url = 'https://api.deepseek.com'
)
for trunk in llm.stream('你是谁'):
print(trunk.content, end='')
print('结束')
还可以每次返回和之前的返回拼接在一起
无数trunk对象通过+加在一起,底层是用重写
__add__()方法运算符重载实现
from langchain.chat_models import init_chat_model
import os
llm = init_chat_model(
model = 'deepseek-chat',
model_provider = 'openai',
api_key = os.getenv('DSKEY'),
base_url = 'https://api.deepseek.com'
)
full = None
for trunk in llm.stream('用一句话介绍自己'):
full = trunk if full is None else full + trunk
print(full.text)
print(full.content_blocks)
print('结束')
print(full.content_blocks)
运行结果:
[]
你好
[{'type': 'text', 'text': '你好'}]
你好,
[{'type': 'text', 'text': '你好,'}]
你好,我是
[{'type': 'text', 'text': '你好,我是'}]
你好,我是Deep
[{'type': 'text', 'text': '你好,我是Deep'}]
你好,我是DeepSe
[{'type': 'text', 'text': '你好,我是DeepSe'}]
你好,我是DeepSeek
[{'type': 'text', 'text': '你好,我是DeepSeek'}]
你好,我是DeepSeek,
[{'type': 'text', 'text': '你好,我是DeepSeek,'}]
你好,我是DeepSeek,一个
[{'type': 'text', 'text': '你好,我是DeepSeek,一个'}]
你好,我是DeepSeek,一个由
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由'}]
你好,我是DeepSeek,一个由深度
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度'}]
你好,我是DeepSeek,一个由深度求
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求'}]
你好,我是DeepSeek,一个由深度求索
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索'}]
你好,我是DeepSeek,一个由深度求索公司
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司'}]
你好,我是DeepSeek,一个由深度求索公司创造的
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊'}]
结束
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊'}]
2.异步
langchain支持异步任务调用大模型,将invoke()换成ainvoke()即可
langchain中异步方法一般就是同步方法的方法名加一个'a'
import asyncio
from langchain.chat_models import init_chat_model
import os
llm = init_chat_model(
model = 'deepseek-chat',
model_provider = 'openai',
api_key = os.getenv('DSKEY'),
base_url = 'https://api.deepseek.com'
)
async def main():
task1 = llm.ainvoke('你是谁')
task2 = llm.ainvoke('你能做什么')
v1 = await task1
v2 = await task2
print('v1', v1)
print('v2', v2)
if __name__ == '__main__':
asyncio.run(main())
异步流式,可实现两路请求同时实时返回大模型回答到程序中,出现两路控制台打印,可以提升吞吐量,异步流式返回异步生成器,遍历生成器时,要用异步for循环async for
flush=True刷新缓冲区,实现流式打印
import asyncio
from langchain.chat_models import init_chat_model
import os
llm = init_chat_model(
model = 'deepseek-chat',
model_provider = 'openai',
api_key = os.getenv('DSKEY'),
base_url = 'https://api.deepseek.com'
)
async def main():
async for trunk in llm.astream('你是谁'):
print(trunk.content, end='', flush=True)
async for trunk in llm.astream('你能做什么'):
print(trunk.content, end='', flush=True)
if __name__ == '__main__':
asyncio.run(main())
3.批处理
有时,需要向大模型发出不止一个问题,需要一次性回答完后一起得到结果,就用到了批处理batch()
from langchain.chat_models import init_chat_model
import os
from dotenv import load_dotenv
load_dotenv(encoding='utf-8')
llm = init_chat_model(
model = 'deepseek-chat',
model_provider = 'openai',
api_key = os.getenv('DEEPSEEK_API_KEY'),
base_url = 'https://api.deepseek.com'
)
questions = [
'你是谁',
'一句话介绍什么是neo4j',
'一句话介绍什么是php'
]
lst = llm.batch(questions)
for q, a in zip(questions, lst):
print(f'问题:{q},回答:{a.content}')
问题:你是谁,回答:你好!我是DeepSeek,由深度求索公司创造的AI助手。我是最新版本的DeepSeek模型,专门设计来帮助你解答问题、提供信息和进行对话。
我的一些特点包括:
- **免费使用**:完全免费,没有任何收费计划
- **强大的处理能力**:支持100万token的上下文,可以一次性处理像《三体》三部曲这样的大部头书籍
- **文件处理**:可以上传并读取图片、PDF、Word、Excel、PPT等文件中的文字信息
- **联网搜索**:支持联网查询最新信息(需要手动开启)
- **多平台支持**:提供Web端和App端,App还支持语音输入
有什么我可以帮你的吗?无论是学习、工作还是日常生活中的问题,我都很乐意为你提供帮助!😊
问题:一句话介绍什么是neo4j,回答:Neo4j 是一个高性能的图数据库,它以节点、关系和属性的图形结构来存储和查询高度关联的数据。
问题:一句话介绍什么是php,回答:PHP是一种主要用于Web开发的服务器端脚本语言,能嵌入HTML中动态生成网页内容。
异步批处理
import asyncio
from langchain.chat_models import init_chat_model
import os
from dotenv import load_dotenv
load_dotenv(encoding='utf-8')
llm = init_chat_model(
model = 'deepseek-chat',
model_provider = 'openai',
api_key = os.getenv('DEEPSEEK_API_KEY'),
base_url = 'https://api.deepseek.com'
)
questions = [
'你是谁',
'一句话介绍什么是neo4j',
'一句话介绍什么是php'
]
async def main():
lst = await llm.abatch(questions)
for q, a in zip(questions, lst):
print(f'问题:{q},回答:{a.content}')
if __name__ == '__main__':
asyncio.run(main())
4.提示词模板
提示词经历了从简单的纯字符串提问,到占位符动态问题,再到多角色消息的历程,在和大语言模型交互时,通常不会原样将用户输入传递给大模型,而是进行相应的包装,组织和格式化,便于更清晰的表达意图,更好的利用模型能力。
常用提示词模板有PromptTemplate,ChatPromptTemplate,PipelinePrompt等。
4.1 PromptTemplate
PromptTemplate是最基础的提示词模板,通过格式化字符串生成提示词,常见参数:
template字符串,包含占位符的模板({})的提示词input_variables列表,变量名称列表,传入时会进行替换partial_variables字典,提示词模板携带的部分变量字典,预先填充一些值,调用时无需再额外传入
可通过构造方法和PromptTemplate.from_template()工厂方法构造PromptTemplate,并且PromptTemplate对象有几个常见方法:
format()invoke()partial()
例:使用构造方法构建PromptTemplate,format()方法为role创建默认值
通过format()方法格式化,一定要对input_variables中的变量赋值,否则会报错,如未设置则忽略,如果一个变量指定了默认值,也可以在调用时进行更换
from langchain_core.prompts import PromptTemplate
template = PromptTemplate(
template='你是一个{role},请回答问题:{question}',
input_variables=['role', 'question'],
partial_variables={'role' : '教师'}
)
prompt = template.format(question='二次函数是什么')
print(prompt) #你是一个教师,请回答问题:二次函数是什么
覆盖默认值
from langchain_core.prompts import PromptTemplate
template = PromptTemplate(
template='你是一个{role},请回答问题:{question}',
input_variables=['role', 'question'],
partial_variables={'role', '教师'}
)
prompt = template.format(question='二次函数是什么', role='高中数学教师')
print(prompt) #你是一个高中数学教师,请回答问题:二次函数是什么
例:使用from_template()方法来构建PromptTemplate
from langchain_core.prompts import PromptTemplate
template = PromptTemplate.from_template('你是一个{role},请回答问题:{question}')
prompt = template.format(question='二次函数是什么', role='高中数学教师')
print(prompt)
你是一个高中数学教师,请回答问题:二次函数是什么
例:增强版的format():使用template.invoke({})直接将生成的提示词转换为StringPromptValue,并通过StringPromptValue的方法获得信息。
from langchain_core.prompts import PromptTemplate
template = PromptTemplate.from_template('你是一个{role},请回答问题:{question}')
prompt = template.invoke({'question':'二次函数是什么', 'role':'高中数学教师'})
print(type(prompt))
print(prompt.to_string())
print(prompt.to_messages())
<class 'langchain_core.prompt_values.StringPromptValue'>
你是一个高中数学教师,请回答问题:二次函数是什么
[HumanMessage(content='你是一个高中数学教师,请回答问题:二次函数是什么', additional_kwargs={}, response_metadata={})]
例:通过partial()方法,将提示词的部分拼装和加载
from langchain_core.prompts import PromptTemplate
template = PromptTemplate.from_template('你是一个{role},请回答问题:{question}')
partial = template.partial(role='高中数学教师')
print(partial)
print(type(partial))
partial = partial.format(question='什么是函数')
print(partial)
print(type(partial))
input_variables=['question'] input_types={} partial_variables={'role': '高中数学教师'} template='你是一个{role},请回答问题:{question}'
<class 'langchain_core.prompts.prompt.PromptTemplate'>
你是一个高中数学教师,请回答问题:什么是函数
<class 'str'>
例:PromptTemplate提示词对象调用大模型
from langchain.chat_models import init_chat_model
import os
from langchain_core.prompts import PromptTemplate
llm = init_chat_model(
model = 'deepseek-chat',
model_provider = 'openai',
api_key = os.getenv('DSKEY'),
base_url = 'https://api.deepseek.com'
)
prompt_template = PromptTemplate(
template='做一个关于{topic}的小诗',
input_variables=['topic']
)
prompt = prompt_template.invoke({'topic': '霸道总裁爱上做保洁的我'})
resp = llm.invoke(prompt)
print(resp)
提示词模板的调用如要想流式,只要改成llm.stream(...)即可
for trunk in llm.stream(prompt):
print(trunk.content, end='')
4.2 ChatPromptTemplate
ChatPromptTemplate是langchain中专门用于结构化聊天对话提示的核心组件,比起普通的PromptTemplate更适合处理多角色,多轮次的对话场景,为现代聊天模型交互提供了一种上下文丰富和会话友好的形式。
ChatPromptTemplate参数都是列表类型,列表的元素可以是字符串,字典,字符串元组,消息类型,提示词模板类型,消息提示词模板类型等。
ChatPromptTemplate通过构造方法或from_messages()来实例化
例:构造方法
消息类 角色名(role) 含义 SystemMessagesystem系统指令 HumanMessageuser/human用户消息 AIMessageassistant/aiAI 回复 ToolMessagetool工具执行结果
from langchain_core.prompts import ChatPromptTemplate
template1 = ChatPromptTemplate(
[
('system', '你是一个AI编程助手,名字叫:{name}'),
('human', '你好'),
('ai', '你好, 有什么问题'),
('human', '{question}')
]
)
prompt = template1.format_messages(name='小团', question='帮我订外卖')
print(prompt)
[SystemMessage(content='你是一个AI编程助手,名字叫:小团', additional_kwargs={}, response_metadata={}), HumanMessage(content='你好', additional_kwargs={}, response_metadata={}), AIMessage(content='你好, 有什么问题', additional_kwargs={}, response_metadata={}, tool_calls=[], invalid_tool_calls=[]), HumanMessage(content='帮我订外卖', additional_kwargs={}, response_metadata={})]
例:from_messages()构造
from langchain_core.prompts import ChatPromptTemplate
template2 = ChatPromptTemplate.from_messages(
[
('system', '你是一个AI编程助手,名字叫:{name}'),
('human', '你好'),
('ai', '你好, 有什么问题'),
('human', '{question}'),
]
)
prompt = template2.format_messages(name='小团', question='帮我订外卖')
print(prompt)
[SystemMessage(content='你是一个AI编程助手,名字叫:小团', additional_kwargs={}, response_metadata={}), HumanMessage(content='你好', additional_kwargs={}, response_metadata={}), AIMessage(content='你好, 有什么问题', additional_kwargs={}, response_metadata={}, tool_calls=[], invalid_tool_calls=[]), HumanMessage(content='帮我订外卖', additional_kwargs={}, response_metadata={})]
上面例子传给ChatPromptTemplate的提示词列表,列表内都是元组类型,除了元组,还支持其他几种形式,按照场景需要可以自由选择。
例如:使用具体的消息类型
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage
from langchain_core.prompts import ChatPromptTemplate
template = ChatPromptTemplate(
[
SystemMessage(content='你是一个AI编程助手,名字叫:{name}') ,
HumanMessage(content='你好'),
AIMessage(content='你好, 有什么问题'),
HumanMessage(content='{question}'),
ToolMessage(content='', tool_call_id='')
]
)
prompt = template.format_messages(name='小团', question='帮我订外卖')
print(prompt)
[SystemMessage(content='你是一个AI编程助手,名字叫:{name}', additional_kwargs={}, response_metadata={}), HumanMessage(content='你好', additional_kwargs={}, response_metadata={}), AIMessage(content='你好, 有什么问题', additional_kwargs={}, response_metadata={}, tool_calls=[], invalid_tool_calls=[]), HumanMessage(content='{question}', additional_kwargs={}, response_metadata={}), ToolMessage(content='', tool_call_id='')]
还可以使用字典类型
from langchain_core.prompts import ChatPromptTemplate
template = ChatPromptTemplate.from_messages([
{
"role": "system",
"content": "你是一个AI编程助手,名字叫:{name}"
},
{
"role": "human",
"content": "你好"
},
{
"role": "ai",
"content": "你好, 有什么问题"
},
{
"role": "human",
"content": "{question}"
}
])
prompt = template.format_messages(name='小团', question='帮我订外卖')
print(prompt)
[SystemMessage(content='你是一个AI编程助手,名字叫:小团', additional_kwargs={}, response_metadata={}), HumanMessage(content='你好', additional_kwargs={}, response_metadata={}), AIMessage(content='你好, 有什么问题', additional_kwargs={}, response_metadata={}, tool_calls=[], invalid_tool_calls=[]), HumanMessage(content='帮我订外卖', additional_kwargs={}, response_metadata={})]
有时,我们不知道消息何时生成,也不知道消息到底有多少条,比如在提示词中添加一些聊天历史形成会话记忆等,这时,ChatPromptTemplate支持消息占位符MessagesPlaceholder
例:显式的指定memory是不确定的对话内容
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
template = ChatPromptTemplate.from_messages(
[
('system', '你是一个出行助手,名字叫:{name}'),
MessagesPlaceholder('memory'),
('human', '你好')
]
)
prompt = template.format_messages(
name='小团',
question='帮我订酒店',
memory=[
('human', '你好,需要阳面的房间')
]
)
print(prompt)
prompt = template.invoke({
'name': '小团',
'question': '帮我订酒店',
'memory': [
('human', '你好,需要阳面的房间')
]
})
print(prompt)
[SystemMessage(content='你是一个出行助手,名字叫:小团', additional_kwargs={}, response_metadata={}), HumanMessage(content='你好,需要阳面的房间', additional_kwargs={}, response_metadata={}), HumanMessage(content='你好', additional_kwargs={}, response_metadata={})]
messages=[SystemMessage(content='你是一个出行助手,名字叫:小团', additional_kwargs={}, response_metadata={}), HumanMessage(content='你好,需要阳面的房间', additional_kwargs={}, response_metadata={}), HumanMessage(content='你好', additional_kwargs={}, response_metadata={})]
MessagesPlaceholder不具备存储功能,仅是占位拼装,重要对话数据还是需要存储在外部数据库
还有隐式的用法,采用('placeholder', '{memory}')的元组写法
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
template = ChatPromptTemplate.from_messages(
[
('system', '你是一个出行助手,名字叫:{name}'),
('placeholder', '{memory}'),
('human', '你好')
]
)
传给大模型进行回答
import os
from langchain.chat_models import init_chat_model
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
llm = init_chat_model(
model = 'deepseek-chat',
model_provider = 'openai',
api_key = os.getenv('DSKEY'),
base_url = 'https://api.deepseek.com'
)
template = ChatPromptTemplate.from_messages(
[
('system', '你是一个出行助手,名字叫:{name}'),
MessagesPlaceholder('memory'),
('human', '你好')
]
)
prompt = template.format_messages(
name='小团',
question='帮我订酒店',
memory=[
('human', '你好,需要阳面的房间')
]
)
resp = llm.invoke(prompt)
print(resp)
4.3 外部加载
代码和配置分离是一种常见的开发规范,因此langchain支持提示词外部加载,有时提示词不适合写死在代码中,甚至有时可能存在将一部小说传给大模型的测试案例,不可能将大段文字写进python文件,因此可以通过将提示词提前保存为json,yml等方式,通过指定路径读取到程序。
以json为例:
{
"_type": "prompt",
"input_variables": ["name", "question"],
"template": "你是一个AI编程助手,名字叫:{name}\n你好\n你好, 有什么问题\n{question}\n",
"template_format": "f-string"
}
from langchain_core.prompts import load_prompt
template = load_prompt('prompt.json', encoding='utf-8')
prompt = template.format_prompt(question='二次函数是什么', name='小美老师')
print(prompt.to_messages() )
5.输出解析器Parsers
大模型的输出,对接不同系统,希望输出不同的格式,langchain提供了输出解析器langchain_core.output_parsers实现获取模型输出转换为不同的格式化内容。输出解析器不但能指定格式输出,还能进行校验和错误处理。
langchain提供了几种常见输出解析器:
| 类型 | 场景 | 格式 |
|---|---|---|
StrOutputParser |
简单文本输出 | 字符串 |
JsonOutputParser |
json格式数据 | 字典/列表 |
PydanticOutputParser |
复杂结构化数据 | Pydantic模型 |
ListOutputParser |
列表数据 | python列表 |
DatetimeOutputParser |
时间日期数据 | datetime对象 |
BooleanOutputParser |
布尔类型 | True/False |
解析器有两个重要的方法:
-
parse()将大模型输出内容,转换成指定的格式 -
get_format_instructions()返回一段清晰的格式说明字符串,告诉大模型希望输出什么格式,比如json或特定的格式
例:JsonOutputParser,将大模型返回转换为python的数据结构(parse())
from langchain.chat_models import init_chat_model
import os
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate
from loguru import logger
llm = init_chat_model(
model = 'deepseek-chat',
model_provider = 'openai',
api_key = os.getenv('DSKEY'),
base_url = 'https://api.deepseek.com'
)
prompt_template = PromptTemplate(
template='回答一个关于{topic}的问题,以json形式返回,json字段q是问题,a是答案',
input_variables=['topic']
)
prompt = prompt_template.invoke({'topic': '什么是php'})
parser = JsonOutputParser()
res = llm.invoke(prompt)
logger.info( f'大模型返回:{res}', )
json = parser.invoke(res)
logger.info(f'解析器解析:{json}',)
logger.info( type(json) )
2026-07-16 22:02:37.745 | INFO | __main__:<module>:26 - 大模型返回:content='{\n "q": "什么是PHP?",\n "a": "PHP(Hypertext Preprocessor,超文本预处理器)是一种广泛使用的开源服务器端脚本语言,特别适用于Web开发。它由Rasmus Lerdorf于1994年创建,最初是'Personal Home Page'的缩写,后改名为递归缩写'PHP: Hypertext Preprocessor'。PHP脚本在服务器上执行,生成动态网页内容,可嵌入HTML中。它支持多种数据库(如MySQL、PostgreSQL)、面向对象编程,并拥有丰富的框架(如Laravel、Symfony)和内容管理系统(如WordPress)。PHP的特点是易于学习、跨平台、高效且社区活跃,常用于构建网站、API和Web应用程序。"\n}' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 154, 'prompt_tokens': 25, 'total_tokens': 179, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 25}, 'model_provider': 'openai', 'model_name': 'deepseek-v4-flash', 'system_fingerprint': 'fp_8b330d02d0_prod0820_fp8_kvcache_20260402', 'id': '66d45c5c-8456-4556-8eae-e0fc5755c40b', 'finish_reason': 'stop', 'logprobs': None} id='lc_run--019f6b3c-7d7a-7c63-a534-af100fb88b5d-0' tool_calls=[] invalid_tool_calls=[] usage_metadata={'input_tokens': 25, 'output_tokens': 154, 'total_tokens': 179, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}
2026-07-16 22:02:37.745 | INFO | __main__:<module>:30 - 解析器解析:{'q': '什么是PHP?', 'a': 'PHP(Hypertext Preprocessor,超文本预处理器)是一种广泛使用的开源服务器端脚本语言,特别适用于Web开发。它由Rasmus Lerdorf于1994年创建,最初是'Personal Home Page'的缩写,后改名为递归缩写'PHP: Hypertext Preprocessor'。PHP脚本在服务器上执行,生成动态网页内容,可嵌入HTML中。它支持多种数据库(如MySQL、PostgreSQL)、面向对象编程,并拥有丰富的框架(如Laravel、Symfony)和内容管理系统(如WordPress)。PHP的特点是易于学习、跨平台、高效且社区活跃,常用于构建网站、API和Web应用程序。'}
2026-07-16 22:02:37.745 | INFO | __main__:<module>:31 - <class 'dict'>
例:使用get_format_instructions()指导模型输出我需要的json格式
from langchain.chat_models import init_chat_model
import os
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate
from loguru import logger
from pydantic import Field, BaseModel
import warnings
from pydantic.json_schema import PydanticJsonSchemaWarning
warnings.filterwarnings("ignore", category=PydanticJsonSchemaWarning)
llm = init_chat_model(
model = 'deepseek-chat',
model_provider = 'openai',
api_key = os.getenv('DSKEY'),
base_url = 'https://api.deepseek.com'
)
class News(BaseModel):
time: str = Field(None, description='时间'),
person: str = Field(None, description='人物'),
event: str = Field(None, description='事件')
parser = JsonOutputParser(pydantic_object=News)
format_instructions = parser.get_format_instructions()
prompt_template = PromptTemplate(
template='回答一个关于{topic}的问题,{format_instructions}',
input_variables=['topic']
)
prompt = prompt_template.invoke(
{
'topic': '2020年,世界上发生了哪些大事',
'format_instructions': format_instructions
}
)
logger.info( f'提示词:{prompt.to_string()}', )
res = llm.invoke(prompt)
logger.info( f'大模型返回:{res}', )
json = parser.invoke(res)
logger.info(f'解析器解析:{json}',)
logger.info( type(json) )
2026-07-16 22:27:16.285 | INFO | __main__:<module>:43 - 提示词:回答一个关于2020年,世界上发生了哪些大事的问题,STRICT OUTPUT FORMAT:
- Return only the JSON value that conforms to the schema. Do not include any additional text, explanations, headings, or separators.
- Do not wrap the JSON in Markdown or code fences (no ``` or ```json).
- Do not prepend or append any text (e.g., do not write "Here is the JSON:").
- The response must be a single top-level JSON value exactly as required by the schema (object/array/etc.), with no trailing commas or comments.
The output should be formatted as a JSON instance that conforms to the JSON schema below.
As an example, for the schema {"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]} the object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema. The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.
Here is the output schema (shown in a code block for readability only --- do not include any backticks or Markdown in your output):
```
{"properties": {"time": {"title": "Time", "type": "string"}, "person": {"title": "Person", "type": "string"}, "event": {"default": null, "description": "事件", "title": "Event", "type": "string"}}}
```
2026-07-16 22:27:18.289 | INFO | __main__:<module>:46 - 大模型返回:content='{"time":"2020","person":"全球","event":"COVID-19疫情被世界卫生组织宣布为全球大流行"}{"time":"2020年1月31日","person":"英国","event":"英国正式脱离欧盟"}{"time":"2020年11月3日","person":"乔·拜登","event":"在美国总统大选中击败唐纳德·特朗普,当选美国第46任总统"}{"time":"2020年5月25日","person":"乔治·弗洛伊德","event":"遭警察暴力执法致死,引发全球反种族歧视抗议浪潮"}' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 122, 'prompt_tokens': 330, 'total_tokens': 452, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 330}, 'model_provider': 'openai', 'model_name': 'deepseek-v4-flash', 'system_fingerprint': 'fp_8b330d02d0_prod0820_fp8_kvcache_20260402', 'id': 'f7f4a1b6-9fe8-4121-bc1a-4cab8a07f9a4', 'finish_reason': 'stop', 'logprobs': None} id='lc_run--019f6b53-1abe-7c01-9f6c-6b81cf2de370-0' tool_calls=[] invalid_tool_calls=[] usage_metadata={'input_tokens': 330, 'output_tokens': 122, 'total_tokens': 452, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}
2026-07-16 22:27:18.292 | INFO | __main__:<module>:50 - 解析器解析:{'time': '2020', 'person': '全球', 'event': 'COVID-19疫情被世界卫生组织宣布为全球大流行'}
2026-07-16 22:27:18.293 | INFO | __main__:<module>:51 - <class 'dict'>