提示词版本管理与测试平台搭建
核心知识点讲解
什么是提示词版本管理?
提示词版本管理是一种管理和追踪提示词变更的方法,它允许团队协作开发、测试和部署提示词,同时保持对提示词历史版本的记录和追溯能力。
提示词版本管理的核心目标:
- 追踪提示词的变更历史
- 支持团队协作开发
- 便于回滚到之前的版本
- 确保提示词的质量和一致性
- 促进提示词的持续改进
为什么需要提示词版本管理?
在构建AI智能体时,提示词版本管理尤为重要,因为:
迭代优化:提示词需要不断迭代和优化,版本管理可以追踪这些变化
团队协作:多个开发者可能同时修改提示词,需要协调和管理这些变更
质量保证:需要确保提示词的质量和可靠性,避免引入错误
合规要求:某些行业可能有合规要求,需要保留提示词的历史记录
问题排查:当出现问题时,需要能够回滚到之前的版本并分析原因
提示词版本管理的最佳实践
提示词版本管理的最佳实践包括:
使用版本控制系统:使用Git等版本控制系统管理提示词文件
建立分支策略:为不同的功能或实验创建分支
编写详细的提交信息:记录每次变更的原因和内容
定期合并和发布:定期合并测试通过的提示词到主分支
建立审批流程:对重要的提示词变更进行审批
文档化:为提示词编写文档,说明其用途、参数和使用方法
什么是提示词测试平台?
提示词测试平台是一种用于测试、评估和优化提示词的系统,它可以自动化测试过程,评估提示词的性能,并提供反馈和改进建议。
提示词测试平台的核心功能:
- 自动化测试提示词
- 评估提示词的性能
- 生成测试报告
- 提供改进建议
- 支持A/B测试
- 集成版本控制系统
提示词测试的重要性
提示词测试对于确保AI智能体的质量和可靠性至关重要,因为:
质量保证:测试可以确保提示词生成的输出符合预期
性能评估:测试可以评估提示词在不同场景下的性能
问题发现:测试可以发现提示词中的问题和缺陷
优化指导:测试结果可以指导提示词的优化方向
回归测试:测试可以确保变更不会破坏现有功能
提示词测试的方法和指标
提示词测试的方法和指标包括:
1. 测试方法
- 单元测试:测试提示词在特定场景下的表现
- 集成测试:测试提示词与其他组件的集成
- 端到端测试:测试完整的用户流程
- A/B测试:比较不同提示词的性能
- 压力测试:测试提示词在高负载下的表现
2. 评估指标
- 准确性:输出是否符合事实和预期
- 相关性:输出是否与输入相关
- 一致性:相同输入是否产生一致的输出
- 完整性:输出是否包含所有必要的信息
- 清晰度:输出是否清晰易懂
- 安全性:输出是否包含有害或不当内容
- 效率:生成输出所需的时间和资源
实用案例分析
案例一:电商客服智能体的提示词管理
场景描述:
一个电商平台部署了客服智能体,需要管理和测试多个提示词,以确保智能体能够正确回答用户的问题。
传统方法:
提示词存储在本地文件中,没有版本控制,测试依赖人工评估。
优化方法:
- 使用Git管理提示词:将提示词存储在Git仓库中,追踪变更历史
- 建立分支策略:为不同的功能(如订单查询、退货处理等)创建分支
- 自动化测试:编写测试用例,自动测试提示词的性能
- A/B测试:比较不同提示词的效果,选择最佳版本
- 持续集成:每次提交后自动运行测试,确保提示词的质量
应用效果:
- 提示词的变更历史可追踪
- 团队协作更加高效
- 提示词的质量和可靠性得到保证
- 智能体的回答准确率显著提高
案例二:金融咨询智能体的测试平台
场景描述:
一个金融机构部署了咨询智能体,需要确保提示词能够生成准确、合规的金融建议。
传统方法:
人工测试,依赖专家评估,测试覆盖范围有限。
优化方法:
- 搭建测试平台:开发专门的测试平台,自动化测试过程
- 定义评估指标:制定金融领域特定的评估指标,如准确性、合规性等
- 创建测试数据集:收集各种金融场景的测试数据
- 自动化评估:使用规则和模型自动评估提示词的输出
- 生成测试报告:提供详细的测试报告,包括性能指标和改进建议
应用效果:
- 测试覆盖范围显著扩大
- 测试效率提高,节省人力成本
- 提示词的质量和合规性得到保证
- 智能体的金融建议更加准确和可靠
案例三:医疗助手智能体的提示词管理和测试
场景描述:
一个医疗科技公司开发了医疗助手智能体,需要确保提示词能够生成准确、安全的医疗信息。
传统方法:
提示词存储在本地,测试依赖医疗专家的人工评估。
优化方法:
- 建立版本管理系统:使用Git管理提示词,建立分支策略和审批流程
- 搭建测试平台:开发专门的测试平台,集成医疗知识库
- 制定评估标准:与医疗专家合作,制定医疗信息准确性和安全性的评估标准
- 自动化测试:使用医疗知识库自动测试提示词的输出
- 定期审核:医疗专家定期审核提示词和测试结果
应用效果:
- 提示词的变更历史可追踪,满足合规要求
- 测试覆盖范围扩大,发现更多潜在问题
- 提示词的质量和安全性得到保证
- 智能体的医疗建议更加准确和可靠
代码示例
示例1:使用Git管理提示词
# 初始化Git仓库
mkdir prompt-engineering
cd prompt-engineering
git init
# 创建提示词目录结构
mkdir -p prompts/{customer_service,finance,healthcare}
# 创建示例提示词文件
echo "你是一位专业的客服代表,擅长回答用户关于产品的问题。请以友好、专业的语气回答用户的问题。" > prompts/customer_service/basic.md
# 提交初始版本
git add .
git commit -m "初始化提示词仓库,添加客服基本提示词"
# 创建功能分支
git checkout -b feature/order-processing
# 修改提示词
echo "你是一位专业的客服代表,擅长处理订单相关的问题。请以友好、专业的语气回答用户的问题,提供准确的订单信息。" > prompts/customer_service/order-processing.md
# 提交变更
git add .
git commit -m "添加订单处理提示词"
# 切换到主分支
git checkout main
# 合并功能分支
git merge feature/order-processing
# 标签发布
git tag v1.0.0示例2:使用Python脚本测试提示词
import openai
import json
import csv
from datetime import datetime
# 设置API密钥
openai.api_key = "YOUR_API_KEY"
# 定义测试用例
test_cases = [
{
"id": "1",
"prompt": "你是一位专业的客服代表,擅长回答用户关于产品的问题。请以友好、专业的语气回答用户的问题。",
"input": "我的订单什么时候能发货?",
"expected": "包含发货时间相关信息"
},
{
"id": "2",
"prompt": "你是一位专业的客服代表,擅长回答用户关于产品的问题。请以友好、专业的语气回答用户的问题。",
"input": "如何申请退货?",
"expected": "包含退货流程相关信息"
}
]
# 定义评估函数
def evaluate_response(response, expected):
"""评估响应是否符合预期"""
# 简单的评估逻辑,实际应用中可以更复杂
score = 0
if expected in response:
score += 0.5
if "友好" in response.lower() or "专业" in response.lower():
score += 0.3
if len(response) > 50:
score += 0.2
return score
# 运行测试
def run_tests(test_cases):
"""运行测试用例"""
results = []
timestamp = datetime.now().isoformat()
for test_case in test_cases:
print(f"运行测试用例 {test_case['id']}...")
# 构建完整提示词
full_prompt = f"{test_case['prompt']}\n\n用户问题:{test_case['input']}\n\n回答:"
# 调用API
try:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": full_prompt}],
temperature=0
)
# 提取响应
answer = response.choices[0].message.content
# 评估响应
score = evaluate_response(answer, test_case['expected'])
# 记录结果
result = {
"timestamp": timestamp,
"test_id": test_case['id'],
"prompt": test_case['prompt'],
"input": test_case['input'],
"expected": test_case['expected'],
"actual": answer,
"score": score,
"passed": score >= 0.6
}
results.append(result)
print(f"测试用例 {test_case['id']} {'通过' if result['passed'] else '失败'},得分:{score}")
except Exception as e:
print(f"测试用例 {test_case['id']} 出错:{e}")
result = {
"timestamp": timestamp,
"test_id": test_case['id'],
"prompt": test_case['prompt'],
"input": test_case['input'],
"expected": test_case['expected'],
"actual": f"错误:{str(e)}",
"score": 0,
"passed": False
}
results.append(result)
return results
# 保存测试结果
def save_results(results, filename="test_results.csv"):
"""保存测试结果到CSV文件"""
with open(filename, 'w', newline='', encoding='utf-8') as f:
fieldnames = ['timestamp', 'test_id', 'prompt', 'input', 'expected', 'actual', 'score', 'passed']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
for result in results:
writer.writerow(result)
print(f"测试结果已保存到 {filename}")
# 运行测试并保存结果
if __name__ == "__main__":
results = run_tests(test_cases)
save_results(results)
# 生成测试报告
passed = sum(1 for r in results if r['passed'])
total = len(results)
print(f"\n测试报告:")
print(f"总测试用例:{total}")
print(f"通过测试用例:{passed}")
print(f"失败测试用例:{total - passed}")
print(f"通过率:{passed/total*100:.2f}%")示例3:使用LangChain和Pytest测试提示词
# test_prompts.py
import pytest
from langchain import LLMChain, PromptTemplate
from langchain_openai import OpenAI
# 初始化LLM
llm = OpenAI(temperature=0)
# 定义提示词模板
def create_prompt_template():
return PromptTemplate(
input_variables=["question"],
template="""你是一位专业的客服代表,擅长回答用户关于产品的问题。请以友好、专业的语气回答用户的问题。
用户问题:{question}
回答:"""
)
# 创建LLMChain
def create_chain():
prompt_template = create_prompt_template()
return LLMChain(llm=llm, prompt=prompt_template)
# 测试用例
@pytest.mark.parametrize("question, expected_keywords", [
("我的订单什么时候能发货?", ["发货", "时间", "订单"]),
("如何申请退货?", ["退货", "流程", "申请"]),
("产品有哪些颜色可选?", ["颜色", "可选", "产品"]),
])
def test_customer_service_prompt(question, expected_keywords):
"""测试客服提示词是否能生成包含关键词的回答"""
chain = create_chain()
response = chain.run(question=question)
# 检查响应是否包含预期关键词
for keyword in expected_keywords:
assert keyword in response, f"响应应包含关键词 '{keyword}'"
# 检查响应长度
assert len(response) > 50, "响应长度应大于50个字符"
# 检查响应语气
assert any(word in response.lower() for word in ["您好", "请", "谢谢", "抱歉"]), "响应应包含友好语气词"
# 运行测试
if __name__ == "__main__":
pytest.main([__file__, "-v"])示例4:搭建简单的提示词测试平台
# app.py
from flask import Flask, request, render_template, jsonify
import openai
import json
import csv
from datetime import datetime
app = Flask(__name__)
# 设置API密钥
openai.api_key = "YOUR_API_KEY"
# 加载测试用例
def load_test_cases():
return [
{
"id": "1",
"category": "客服",
"prompt": "你是一位专业的客服代表,擅长回答用户关于产品的问题。请以友好、专业的语气回答用户的问题。",
"input": "我的订单什么时候能发货?",
"expected": "包含发货时间相关信息"
},
{
"id": "2",
"category": "客服",
"prompt": "你是一位专业的客服代表,擅长回答用户关于产品的问题。请以友好、专业的语气回答用户的问题。",
"input": "如何申请退货?",
"expected": "包含退货流程相关信息"
},
{
"id": "3",
"category": "金融",
"prompt": "你是一位专业的金融顾问,擅长提供投资建议。请以专业、客观的语气回答用户的问题。",
"input": "如何开始投资?",
"expected": "包含投资步骤和建议"
}
]
# 评估响应
def evaluate_response(response, expected):
score = 0
if expected in response:
score += 0.5
if "专业" in response or "友好" in response:
score += 0.3
if len(response) > 50:
score += 0.2
return score
# 运行测试
def run_test(test_case):
full_prompt = f"{test_case['prompt']}\n\n用户问题:{test_case['input']}\n\n回答:"
try:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": full_prompt}],
temperature=0
)
answer = response.choices[0].message.content
score = evaluate_response(answer, test_case['expected'])
result = {
"test_id": test_case['id'],
"category": test_case['category'],
"prompt": test_case['prompt'],
"input": test_case['input'],
"expected": test_case['expected'],
"actual": answer,
"score": score,
"passed": score >= 0.6
}
return result
except Exception as e:
return {
"test_id": test_case['id'],
"category": test_case['category'],
"prompt": test_case['prompt'],
"input": test_case['input'],
"expected": test_case['expected'],
"actual": f"错误:{str(e)}",
"score": 0,
"passed": False
}
# 保存测试结果
def save_results(results):
timestamp = datetime.now().isoformat()
filename = f"test_results_{timestamp.replace(':', '-')}.csv"
with open(filename, 'w', newline='', encoding='utf-8') as f:
fieldnames = ['test_id', 'category', 'prompt', 'input', 'expected', 'actual', 'score', 'passed']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
for result in results:
writer.writerow(result)
return filename
# 路由
@app.route('/')
def index():
test_cases = load_test_cases()
return render_template('index.html', test_cases=test_cases)
@app.route('/run-test', methods=['POST'])
def run_test_endpoint():
test_case = request.json
result = run_test(test_case)
return jsonify(result)
@app.route('/run-all-tests', methods=['POST'])
def run_all_tests():
test_cases = load_test_cases()
results = []
for test_case in test_cases:
result = run_test(test_case)
results.append(result)
# 保存结果
filename = save_results(results)
# 计算统计信息
passed = sum(1 for r in results if r['passed'])
total = len(results)
stats = {
"total": total,
"passed": passed,
"failed": total - passed,
"pass_rate": passed/total*100
}
return jsonify({"results": results, "stats": stats, "filename": filename})
if __name__ == '__main__':
app.run(debug=True)<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>提示词测试平台</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<div class="container mt-4">
<h1>提示词测试平台</h1>
<div class="mb-4">
<button id="run-all-tests" class="btn btn-primary">运行所有测试</button>
<div id="stats" class="mt-2"></div>
</div>
<div class="row">
{% for test_case in test_cases %}
<div class="col-md-6 mb-4">
<div class="card">
<div class="card-header">
<h5 class="card-title">测试用例 {{ test_case.id }} - {{ test_case.category }}</h5>
</div>
<div class="card-body">
<div class="mb-2">
<strong>提示词:</strong>
<p>{{ test_case.prompt }}</p>
</div>
<div class="mb-2">
<strong>输入:</strong>
<p>{{ test_case.input }}</p>
</div>
<div class="mb-2">
<strong>预期:</strong>
<p>{{ test_case.expected }}</p>
</div>
<button class="run-test btn btn-sm btn-outline-primary" data-test-id="{{ test_case.id }}">运行测试</button>
</div>
<div class="card-footer test-result" data-test-id="{{ test_case.id }}">
<!-- 测试结果将显示在这里 -->
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<script>
// 运行单个测试
$('.run-test').click(function() {
const testId = $(this).data('test-id');
const testCase = {{ test_cases|tojson }}.find(tc => tc.id === testId);
const resultDiv = $(`.test-result[data-test-id="${testId}"]`);
resultDiv.html('<div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div>');
$.ajax({
url: '/run-test',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(testCase),
success: function(result) {
let statusClass = result.passed ? 'text-success' : 'text-danger';
let statusText = result.passed ? '通过' : '失败';
resultDiv.html(`
<div class="${statusClass}"><strong>测试结果:${statusText}</strong></div>
<div><strong>得分:</strong>${result.score}</div>
<div><strong>实际输出:</strong></div>
<p>${result.actual}</p>
`);
},
error: function() {
resultDiv.html('<div class="text-danger">测试失败</div>');
}
});
});
// 运行所有测试
$('#run-all-tests').click(function() {
$(this).prop('disabled', true).html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> 运行中...');
$.ajax({
url: '/run-all-tests',
type: 'POST',
success: function(data) {
// 更新统计信息
$('#stats').html(`
<div class="alert alert-info">
<strong>测试统计:</strong>
总测试用例:${data.stats.total}<br>
通过:${data.stats.passed}<br>
失败:${data.stats.failed}<br>
通过率:${data.stats.pass_rate.toFixed(2)}%
</div>
`);
// 更新每个测试用例的结果
data.results.forEach(result => {
let statusClass = result.passed ? 'text-success' : 'text-danger';
let statusText = result.passed ? '通过' : '失败';
$(`.test-result[data-test-id="${result.test_id}"]`).html(`
<div class="${statusClass}"><strong>测试结果:${statusText}</strong></div>
<div><strong>得分:</strong>${result.score}</div>
<div><strong>实际输出:</strong></div>
<p>${result.actual}</p>
`);
});
// 恢复按钮状态
$('#run-all-tests').prop('disabled', false).text('运行所有测试');
// 显示下载链接
$('#stats').append(`<a href="/${data.filename}" class="btn btn-sm btn-secondary mt-2">下载测试结果</a>`);
},
error: function() {
$('#stats').html('<div class="alert alert-danger">测试失败</div>');
$('#run-all-tests').prop('disabled', false).text('运行所有测试');
}
});
});
</script>
</body>
</html>示例5:使用MLflow跟踪提示词实验
import mlflow
import openai
import pandas as pd
from datetime import datetime
# 设置API密钥
openai.api_key = "YOUR_API_KEY"
# 初始化MLflow实验
mlflow.set_experiment("提示词优化实验")
# 定义测试用例
test_cases = [
{
"id": "1",
"input": "我的订单什么时候能发货?",
"expected": "包含发货时间相关信息"
},
{
"id": "2",
"input": "如何申请退货?",
"expected": "包含退货流程相关信息"
}
]
# 定义提示词变体
prompt_variants = [
{
"name": "基础版",
"content": "你是一位客服代表,回答用户的问题。"
},
{
"name": "专业版",
"content": "你是一位专业的客服代表,擅长回答用户关于产品的问题。请以友好、专业的语气回答用户的问题。"
},
{
"name": "详细版",
"content": "你是一位专业的客服代表,擅长回答用户关于产品和订单的问题。请以友好、专业的语气回答用户的问题,提供详细、准确的信息,确保用户得到满意的解答。"
}
]
# 评估函数
def evaluate_response(response, expected):
score = 0
if expected in response:
score += 0.5
if "专业" in response or "友好" in response:
score += 0.3
if len(response) > 50:
score += 0.2
return score
# 运行实验
def run_experiment():
results = []
for prompt in prompt_variants:
print(f"测试提示词变体:{prompt['name']}")
with mlflow.start_run(run_name=prompt['name']):
# 记录提示词参数
mlflow.log_param("prompt_name", prompt['name'])
mlflow.log_param("prompt_content", prompt['content'])
# 运行测试用例
total_score = 0
passed_tests = 0
for test_case in test_cases:
full_prompt = f"{prompt['content']}\n\n用户问题:{test_case['input']}\n\n回答:"
try:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": full_prompt}],
temperature=0
)
answer = response.choices[0].message.content
score = evaluate_response(answer, test_case['expected'])
passed = score >= 0.6
total_score += score
if passed:
passed_tests += 1
# 记录单个测试结果
mlflow.log_metric(f"score_test_{test_case['id']}", score)
mlflow.log_metric(f"passed_test_{test_case['id']}", 1 if passed else 0)
# 记录输出
mlflow.log_text(answer, f"output_test_{test_case['id']}.txt")
except Exception as e:
print(f"测试用例 {test_case['id']} 出错:{e}")
mlflow.log_metric(f"score_test_{test_case['id']}", 0)
mlflow.log_metric(f"passed_test_{test_case['id']}", 0)
# 计算平均得分和通过率
avg_score = total_score / len(test_cases)
pass_rate = passed_tests / len(test_cases) * 100
# 记录汇总指标
mlflow.log_metric("average_score", avg_score)
mlflow.log_metric("pass_rate", pass_rate)
mlflow.log_metric("total_passed", passed_tests)
# 保存结果
results.append({
"prompt_name": prompt['name'],
"average_score": avg_score,
"pass_rate": pass_rate,
"total_passed": passed_tests
})
print(f"平均得分:{avg_score}")
print(f"通过率:{pass_rate}%")
print(f"通过测试数:{passed_tests}/{len(test_cases)}")
print("---")
# 显示结果
df = pd.DataFrame(results)
print("实验结果汇总:")
print(df)
if __name__ == "__main__":
run_experiment()总结与思考
关键要点回顾
提示词版本管理的概念:管理和追踪提示词变更的方法,支持团队协作和版本追溯
提示词版本管理的最佳实践:使用Git等版本控制系统,建立分支策略,编写详细的提交信息,定期合并和发布,建立审批流程,文档化
提示词测试平台的概念:用于测试、评估和优化提示词的系统,自动化测试过程,评估提示词性能
提示词测试的方法和指标:单元测试、集成测试、端到端测试、A/B测试、压力测试;准确性、相关性、一致性、完整性、清晰度、安全性、效率
实用案例:电商客服智能体、金融咨询智能体、医疗助手智能体的提示词管理和测试
实践建议
建立版本管理流程:使用Git等版本控制系统管理提示词,建立清晰的分支策略和审批流程
自动化测试:开发自动化测试脚本,定期运行测试,确保提示词的质量
定义评估指标:根据具体任务和领域,定义适合的评估指标
搭建测试平台:搭建专门的测试平台,集成版本控制、自动化测试和评估功能
持续改进:根据测试结果,持续优化提示词,不断提高智能体的性能
团队协作:建立团队协作机制,促进知识共享和最佳实践的传播
监控和分析:监控智能体的实际表现,分析用户反馈,不断调整和优化提示词
未来学习方向
高级版本管理工具:研究和使用专门的提示词版本管理工具,如PromptBase、Promptify等
自动化提示词优化:探索使用机器学习和强化学习自动优化提示词
多模态提示词测试:研究如何测试和评估多模态提示词(如文本-图像、文本-音频)
大规模测试平台:构建支持大规模提示词测试的平台,处理海量测试数据
实时监控系统:开发实时监控系统,监控智能体的实际表现,及时发现和解决问题
提示词市场:探索提示词的商业化可能性,建立提示词市场和交易机制
伦理和合规测试:研究如何测试提示词的伦理和合规性,确保智能体的行为符合道德和法律要求
提示词版本管理和测试平台是构建高质量AI智能体的重要基础设施。通过建立完善的版本管理流程和测试体系,你将能够开发出更加可靠、高效、符合预期的AI助手,为用户提供更好的服务。在接下来的课程中,我们将继续探索提示词工程的其他高级技术,帮助你进一步提升智能体的能力。