玩转Prompt模板与上下文管理:测试工程师进阶LangChain多轮对话机器人

在上一篇中,我们已经掌握了如何用 LangChain 和 LangGraph 快速搭建一个具备多轮记忆能力的测试辅助聊天机器人。但对于追求专业性和高质量交互体验的测试工程师来说,光会“聊天”还远远不够。
如何让机器人说话更贴合业务?如何优雅控制上下文长度?如何流畅输出长文本? 这些实用需求,都能通过 LangChain 的 Prompt 模板、历史管理与流式输出能力轻松搞定。

本篇带你进阶:让你的测试智能助手不仅会“记”,还能“说得专业、聊得流畅”。


一、Prompt模板:让机器人说话有风格、有规范

1. Prompt模板是什么?

Prompt Template(提示模板)就是用来把用户的原始输入,转成 LLM 更好理解、更能按你预期表达的格式。
比如:你希望机器人说话像海盗,可以这样写👇

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

prompt_template = ChatPromptTemplate.from_messages([
    (
        "system",
        "你是一个私人助手,请尽你所能帮我解决我的疑问吧",
    ),
    MessagesPlaceholder(variable_name="messages")
])
  • system:定义机器人说话的风格、定位、行为规范。
  • MessagesPlaceholder:占位符,传入历史消息(对话上下文)。

2. 应用到多轮对话

把 prompt_template 应用到对话链条里:

from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import START, MessagesState, StateGraph

# 定义一个graph
workflow = StateGraph(state_schema=MessagesState)

def call_model(state: MessagesState):
    prompt = prompt_template.invoke(state)
    response = model.invoke(prompt)
    return {"messages": response}

workflow.add_edge(START, "model")
workflow.add_node("model", call_model)
# 记忆保存在内存中
memory = MemorySaver()
app = workflow.compile(checkpointer=memory)

效果
问“Hi! I’m Jim.”,机器人会用“海盗腔”回答你。

config =  {"configurable": {"thread_id": "test_345"}}
query = "Hi I am Jim"
input_messages = [HumanMessage(query)]
output = app.invoke({"messages": input_messages}, config)
output["messages"][-1].pretty_print()
================================== Ai Message ==================================

Hi Jim! 👋 How can I assist you today? Whether you need help with a task, have questions, or just want to chat—I'm here for you. Let me know what's on your mind! 😊
query = "What is my name"
input_messages = [HumanMessage(query)]
output = app.invoke({"messages": input_messages}, config)
output["messages"][-1].pretty_print()
================================== Ai Message ==================================

Your name is **Jim**! 😊 You introduced yourself at the beginning with "Hi I am Jim." Unless you'd like me to call you something else—just let me know!  

How can I help you today, Jim? 🚀

二、让Prompt更灵活:动态参数定制

实际业务中,你可能需要让机器人支持多语言、不同角色等需求。Prompt模板可以用变量动态填充!

prompt_template = ChatPromptTemplate.from_messages([(
    "system",
    "你是一名资深的Python测试开发工程师,生成代码默认以{language}",
),
    MessagesPlaceholder(variable_name="messages")
                                                   ])
  • 这里 {language} 就是动态参数,比如你传入 “python”,回答就会以python代码输出!

1. 状态管理:支持多参数

要让多轮对话记住“语言”参数,只需把 state 扩展一下:

class State(TypedDict):
    messages: Annotated[Sequence[BaseMessage], add_messages]
    language: str
  • messages:对话历史
  • language:当前对话的语言

再调用时,直接传入:

config = {"configurable": {"thread_id": "abc456"}}
query = "给我生成一个冒泡排序的代码"
language = "Python"

input_messages = [HumanMessage(query)]
output = app.invoke(
    {"messages": input_messages, "language": language},
    config,
)
output["messages"][-1].pretty_print()
================================== Ai Message ==================================

以下是一个标准的冒泡排序算法的Python实现:

```python
def bubble_sort(arr):
    """
    冒泡排序算法实现
    
    参数:
        arr (list): 待排序的列表
        
    返回:
        list: 排序后的列表
    """
    n = len(arr)
    
    # 遍历所有数组元素
    for i in range(n):
        # 最后i个元素已经是排好序的
        for j in range(0, n-i-1):
            # 如果当前元素比下一个元素大,则交换它们
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
    
    return arr


# 测试代码
if __name__ == "__main__":
    test_list = [64, 34, 25, 12, 22, 11, 90]
    print("排序前:", test_list)
    sorted_list = bubble_sort(test_list)
    print("排序后:", sorted_list)

输出结果:

排序前: [64, 34, 25, 12, 22, 11, 90]
排序后: [11, 12, 22, 25, 34, 64, 90]

这个实现包含了:

  1. 基本的冒泡排序算法
  2. 详细的注释说明
  3. 测试用例
  4. 时间复杂度为O(n²)

如果需要优化版本(例如添加提前终止标志),可以这样修改:

def optimized_bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        swapped = False
        for j in range(0, n-i-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
                swapped = True
        # 如果没有发生交换,说明已经有序
        if not swapped:
            break
    return arr
**下次只传消息,语言仍然记得!**  
这意味着你可以灵活定制机器人的风格、输出格式、用例详细度等——只需把这些作为state参数即可。

---

## 三、上下文历史管理:让回复始终“刚刚好”

### 为什么要裁剪历史?

LLM 的上下文窗口是有限的(比如 GPT-4o 8k/32k tokens),如果对话历史无限增长,模型会“超载”,导致:
- 消耗大量 API 费用
- 超窗口后无法记住早期内容

### 怎么裁剪?一句代码就够!

```python
from langchain_core.messages import SystemMessage, trim_messages
from langchain_core.messages import AIMessage
import tiktoken
from typing import Tuple
from langchain_openai import ChatOpenAI

class ChatOpenAIForCounter(ChatOpenAI):

    def _get_enccoding_model(str) -> Tuple[str, tiktoken.Encoding]:
        model = "gpt-3.5-turbo"
        return model, tiktoken.encoding_for_model(model)

trim_model = ChatOpenAIForCounter()
trimmer = trim_messages(
    max_tokens=65,
    strategy="last",
    token_counter=trim_model,
    include_system=True,
    allow_partial=False,
    start_on="human",
)

messages_ = [
    SystemMessage(content="you're a good assistant"),
    HumanMessage(content="hi! I'm bob"),
    AIMessage(content="hi!"),
    HumanMessage(content="I like vanilla ice cream"),
    AIMessage(content="nice"),
    HumanMessage(content="whats 2 + 2"),
    AIMessage(content="4"),
    HumanMessage(content="thanks"),
    AIMessage(content="no problem!"),
    HumanMessage(content="having fun?"),
    AIMessage(content="yes!"),
]

trimmer.invoke(messages_)

输出结果可见对历史消息进行了截留。

[SystemMessage(content="you're a good assistant", additional_kwargs={}, response_metadata={}),
 HumanMessage(content='whats 2 + 2', additional_kwargs={}, response_metadata={}),
 AIMessage(content='4', additional_kwargs={}, response_metadata={}),
 HumanMessage(content='thanks', additional_kwargs={}, response_metadata={}),
 AIMessage(content='no problem!', additional_kwargs={}, response_metadata={}),
 HumanMessage(content='having fun?', additional_kwargs={}, response_metadata={}),
 AIMessage(content='yes!', additional_kwargs={}, response_metadata={})]

每次调用前,把历史先“瘦身”:

workflow = StateGraph(state_schema=State)


def call_model(state: State):
    trimmed_messages = trimmer.invoke(state["messages"])
    prompt = prompt_template.invoke({"messages": trimmed_messages, "language": state["language"]})
    response = model.invoke(prompt)
    return {"messages": [response]}


workflow.add_edge(START, "model")
workflow.add_node("model", call_model)

memoroy = MemorySaver()
app = workflow.compile(checkpointer=memory)

效果

  • 只保留最近N条消息+system message,保证模型每次都能“记得刚刚发生的事”,不被旧消息拖慢。
  • 保证多轮对话的“记忆力”总是最适合当前业务。

四、流式输出:让机器人像真人一样“边想边说”

测试工程师肯定有过和 LLM 聊天“等半天”的体验吧?
LangChain 支持流式输出(streaming)——让对话助手想到哪说到哪,秒变“打字机器人”,极大提升交互体验!

config = {"configurable": {"thread_id": "abc789"}}
query = "请帮我生成一个插入排序的代码"
language = "python"
input_messages = [HumanMessage(query)]
for chunk, metadata in app.stream(
    {"messages": input_messages, "language": language}, config, stream_mode="messages",
):
    if isinstance(chunk, AIMessage):
        print(chunk.content, end="")

实际体验

  • 用户输入一长串测试场景或复杂问题,机器人会一边生成一边输出,响应“秒见首句”,极大提升体验。

五、实战场景串讲

1. 用 Prompt 定制专业风格

  • 让机器人自动以“测试专家”的口吻回复
  • 输出测试用例时必须带编号、分级、预期结果等
  • “你是一个精通Web安全测试的专家,请用中文回答所有问题……”

2. 用裁剪保证业务连续性

  • 聊复杂测试项目时,始终记住最近关键信息,不让历史“淹没新问题”
  • 复盘老对话时,精确控制上下文,避免无关信息占据token

3. 用流式提升体验

  • 回答测试报告生成、用例推理等慢任务时,让用户“秒见结果”,大幅降低等待焦虑

六、写给测试工程师的Tips

  • Prompt模板是“机器人性格和业务规范”的入口:写Prompt就像写测试计划,越精细越有效。
  • 状态管理让机器人“记住你的偏好”:比如语言、角色、输出格式、项目编号等,都可以做成state参数。
  • 历史裁剪让多轮对话更持久、更高效:不用担心忘记历史,也不用担心超载。
  • 流式输出让交互体验媲美真人:任何慢任务都能优雅展示进度。

结语

LangChain 让每个测试工程师都能拥有自己的“超级测试助手”——既懂你的业务,又会高效对话,还能输出专业级别的答案。只要用好 Prompt 模板和上下文管理,你的测试机器人将成为团队的“智慧左膀右臂”!

下期预告:如何结合 LangChain、RAG 技术让机器人基于测试用例库/缺陷库实现“知识检索+对话”一体化?
持续关注,测试智能化之路越走越宽!

### 如何在 LangChain 中实现多轮对话 LangChain 是一种用于构建语言模型应用程序的强大框架,支持多种类型的内存管理方式来处理上下文信息。为了实现在 ZHIPU AI 的 GLM-4 模型中的多轮对话功能,可以利用 LangChain 提供的记忆模块 (Memory Modules),这些模块能够存储并检索先前的对话历史记录。 以下是基于 LangChain 和 ZHIPU AI API 实现多轮对话的一个具体方法: #### 使用 ConversationBufferMemory 进行多轮对话 `ConversationBufferMemory` 是 LangChain 提供的一种简单有效的记忆机制,它可以保存最近几轮的对话内容以便后续调用。下面是一个简单的 Python 示例代码展示如何配置和使用该组件[^1]。 ```python from langchain.memory import ConversationBufferMemory from langchain.llms import ZhipuaiAPI # 假设这是连接到 ZHIPU AI 的接口类 from langchain.chains import LLMChain from langchain.prompts import PromptTemplate # 初始化 ZHIPU AI 的大语言模型实例 llm = ZhipuaiAPI(model_name="GLM-4", api_key="your_api_key_here") # 创建一个带有缓冲区的记忆对象 memory = ConversationBufferMemory() # 构建提示模板以包含之前的聊天历史 prompt_template = """The following is a friendly conversation between a human and an AI. Chat History: {chat_history} Human: {human_input} AI:""" PROMPT = PromptTemplate(input_variables=["chat_history", "human_input"], template=prompt_template) # 设置链式结构并将记忆加入其中 conversation_with_memory = LLMChain( llm=llm, prompt=PROMPT, memory=memory, # 将记忆传递给链 ) # 测试多轮对话 response_1 = conversation_with_memory.run(human_input="你好,能帮我写一段关于春天的小故事吗?") print(response_1) response_2 = conversation_with_memory.run(human_input="那再加一句诗吧。") print(response_2) ``` 上述脚本展示了如何初始化 `LLMChain` 并集成 `ConversationBufferMemory` 来跟踪会话的历史记录。每次当用户输入新的问题或者评论时,之前所有的交流都会被自动嵌入到下一次请求里作为背景资料提供给 GLM-4 模型。 #### 配置 Neo4j 向量数据库扩展记忆能力 如果希望进一步提升系统的性能,比如增加长期记忆的功能,则可以通过安装额外插件如 Neo4j 向量数据库来进行更复杂的语义匹配操作。这一步骤可通过命令行完成如下所示[^2]: ```bash langchain app add neo4j-vector-memory ``` 此命令将会把 Neo4j 数据库存储方案引入当前的应用程序环境中,从而允许开发者定义更加精细的数据管理和查询策略。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Python测试之道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值