LangChain Prompt提示词工程

本文未完待续

本文基于Python 1.13.x和LangChain 1.1.2,并采用DeekSeep大模型,介绍LangChain提示词工程的实现。

pip install langchain==1.1.2
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 字典,提示词模板携带的部分变量字典,预先填充一些值,调用时无需再额外传入

通过format()方法格式化,一定要对input_variables中的变量赋值,否则会报错,如未设置则忽略,如果一个变量指定了默认值,也可以在调用时进行更换


例:使用构造方法构建PromptTemplate

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)

from langchain.chat_models import init_chat_model
import os
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableSequence
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']
)

parser = StrOutputParser()

chain = RunnableSequence(prompt_template, llm, parser)


resp = chain.invoke({'topic': '霸道总裁爱上做保洁的我'})

print(resp)

提示词模板的调用如要想流式,只要改成chain.stream(...)即可

4.2 ChatPromptTemplate

ChatPromptTemplate是聊天模型提示词模板,包括SystemMessage,HumanMessage,AIMessage,ToolMessage几种

5.LCEL增强对话功能

要理解LCEL,首先要了解Runable,Runable(langchain_core.runnables.base.Runnable)是langchain中可以调用,批处理,流式输出,转换和组合的工作单元,是实现LCEL的基础,通过重写__or__()方法,实现了|运算符的重载,实现了Runable的类对象之间便可以进行一些类似linux命令中的管道(|)操作。

LCEL,全称LangChain Express Language,即LangChain表达式语言,也是LangChain官方推荐的写法,是一种从Runable而来的声明式方法,用于声明,组合和执行各种组件(模型,提示词,工具等),如果要使用LCEL,对应的组件必须实现Runable,使用LCEL创建的Runable称之为链。

例如,将刚刚提示词模板的例子用LCEL重写

import os

from langchain.chat_models import init_chat_model
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser

prompt_template = PromptTemplate(
    template='做一个关于{topic}的小诗',
    input_variables=['topic']
)

llm = init_chat_model(
    model = 'deepseek-chat',
    model_provider = 'openai',
    api_key = os.getenv('DSKEY'),
    base_url = 'https://api.deepseek.com'
)

parser = StrOutputParser()

# LCEL重写
chain = prompt_template | llm | parser

resp = chain.invoke({'topic': '霸道总裁爱上做保洁的我'})

print(resp)

还可以自定义一个word_count(text: str) -> int函数,通过langchain的RunnableLambda对象包装,使得函数变为获得链式的执行能力的Runable对象,拼入链中,统计大模型回复的字数


import os

from langchain.chat_models import init_chat_model
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableLambda

prompt_template = PromptTemplate(
    template='做一个关于{topic}的小诗',
    input_variables=['topic']
)

llm = init_chat_model(
    model = 'deepseek-chat',
    model_provider = 'openai',
    api_key = os.getenv('DSKEY'),
    base_url = 'https://api.deepseek.com'
)

parser = StrOutputParser()


def word_count(text: str) -> int:
    print('----------word_count---------')
    return len(text)

word_counter = RunnableLambda(word_count)

# LCEL重写
chain = prompt_template | llm | parser | word_counter

resp = chain.invoke({'topic': '霸道总裁爱上做保洁的我'})

print(resp)

运行:

----------word_count---------
232

"如果文章对您有帮助,可以请作者喝杯咖啡吗?"

微信二维码

微信支付

支付宝二维码

支付宝


LangChain Prompt提示词工程
https://blog.liuzijian.com/post/2025/12/12/langchain-prompt/
作者
Liu Zijian
发布于
2025年12月12日
许可协议