LangChain Prompt提示词工程

本文基于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_key API_KEY
  • base_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/tool
  • content 大模型的输出,一般是字符串,多模态模型可能是其他内容
  • name 当消息类型相同,对消息进行区分,不是所有模型都支持
  • response_metadata ai消息才会包含的属性,附加元数据,不同模型内容也是不一样的
  • tool_calls ai消息才会包含的属性,当大模型决定调用某个工具时,就会包含,每个元素是一个字典,包含工具名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) 含义
SystemMessage system 系统指令
HumanMessage user / human 用户消息
AIMessage assistant / ai AI 回复
ToolMessage tool 工具执行结果
复制代码
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'>
相关推荐
小程故事多_802 小时前
拆解SOP+ReAct对话Agent,告别硬编码,解锁智能对话的柔性迭代能力
前端·人工智能·react.js·前端框架
nicole bai2 小时前
vue 自定义模块内容
前端·javascript·vue.js
清水白石0082 小时前
Python 类定义阶段自动注册子类:从 `__init_subclass__` 到插件系统实战
linux·前端·python
用户69371750013843 小时前
Kimi K3 综合能力处于全球第一梯队
android·前端·后端
anno3 小时前
Agent 新手 Skill 优先级指南:从第一套必装工作流,到专业能力补全
前端·后端
拾年2753 小时前
RAG 灵魂三问:你的文档是怎么"喂"给大模型的?
langchain·node.js·llm
陳陈陳3 小时前
LLM的"消化系统":一文讲透RAG文档加载与智能切割
数据库·langchain·llm
Liora_Yvonne3 小时前
前端请求层到底怎么封?为什么全局 axios 单例越用越难维护
前端
anno3 小时前
别再把文档“一刀切”:用 LangChain.js 做好 RAG 的第一公里
前端·后端