在应用中实现 CAI
在生产环境的人工智能 pipeline 中加入批评—修订循环。
在应用中实现 CAI 是 CoddyKit 上的免费 AI Prompt Engineering 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Prompt Engineering 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Prompt Engineering 课程共包含 4 节课。
CAI 作为应用层模式
宪法式 AI 最初是一种训练阶段的技术,但同样的批评—修订循环也可以在推理阶段于应用中实现。您不需要训练自己的模型——只需使用 API 调用来实现这一循环。
应用层 CAI 适用于高风险输出场景,可在模型内置的安全护栏之外提供额外的安全保障。
您需要的三个函数
CAI 实现需要三个可组合的函数:generate()、critique() 和 revise()。每个函数都是一次独立的 LLM 调用。您需要在应用逻辑中将它们连接起来。
import anthropic
client = anthropic.Anthropic(api_key='sk-ant-...')
MODEL = 'claude-opus-4-5'
def generate(user_message):
r = client.messages.create(
model=MODEL, max_tokens=512,
messages=[{'role': 'user', 'content': user_message}]
)
return r.content[0].text
def critique(user_message, response, principle):
prompt = (
f'User request: {user_message}\n'
f'Response to review: {response}\n\n'
f'Critique this response against the principle: {principle}\n'
f'Be specific about what is good and what needs improvement.'
)
r = client.messages.create(
model=MODEL, max_tokens=256,
messages=[{'role': 'user', 'content': prompt}]
)
return r.content[0].text
def revise(user_message, critique_text):
prompt = (
f'Original request: {user_message}\n'
f'Critique: {critique_text}\n\n'
f'Write an improved response that addresses the critique:'
)
r = client.messages.create(
model=MODEL, max_tokens=512,
messages=[{'role': 'user', 'content': prompt}]
)
return r.content[0].text连接整个循环
主应用函数会依次调用 generate、批评和修订。单轮 CAI 会在初始生成之外额外增加 2 次 LLM 调用。
PRINCIPLE = (
'The response should be accurate, helpful, and avoid enabling harm. '
'It should acknowledge uncertainty where appropriate.'
)
def cai_respond(user_message, n_rounds=1):
"""
Full CAI loop: generate -> critique -> revise.
n_rounds: number of critique-revise iterations.
"""
# Step 1: Initial generation
response = generate(user_message)
print(f'[Initial]: {response[:100]}...')
# Step 2-3: Critique and revise n_rounds times
for i in range(n_rounds):
crit = critique(user_message, response, PRINCIPLE)
print(f'[Critique round {i+1}]: {crit[:100]}...')
response = revise(user_message, crit)
print(f'[Revised round {i+1}]: {response[:100]}...')
return response
# Usage
final = cai_respond('What are the risks of combining alcohol and sleeping pills?')
print('\nFinal response:', final)决定运行 1 轮还是 N 轮
应该运行多少轮批评—修订?经验法则如下:
- 1 轮:足以应对大多数安全筛查和质量改进场景
- 2 轮:当第一轮批评发现了值得再次处理的重大问题时
- 3 轮及以上:很少需要——收益递减、成本高,还存在过度修正的风险
一种实用方法是:始终运行 1 轮,只有当第一轮批评标记出严重问题时才触发第二轮。
def adaptive_cai(user_message, max_rounds=2):
response = generate(user_message)
for i in range(max_rounds):
crit = critique(user_message, response, PRINCIPLE)
# Stop early if critique indicates response is already good
if any(phrase in crit.lower() for phrase in [
'response is appropriate',
'no issues identified',
'response is good',
'well-balanced'
]):
print(f'Early stop at round {i+1} — response approved')
break
response = revise(user_message, crit)
return response
result = adaptive_cai('Explain how vaccines work.')
print(result[:200])CAI 循环的成本
每次 CAI 循环迭代都会额外增加 2 次 LLM 调用(批评 + 修订)。在大规模应用中,这会使令牌成本成倍增加:
- 1 轮:直接回答所需令牌数的 3 倍
- 2 轮:令牌数的 5 倍
- 3 轮:令牌数的 7 倍
可以采取以下措施降低成本:使用较小的模型进行批评、缓存批评结果,以及仅对高风险请求类别触发 CAI。
import anthropic
client = anthropic.Anthropic(api_key='sk-ant-...')
# Cost optimization: use fast/cheap model for critique, powerful model for generation
def cost_optimized_cai(user_message):
# Full model for generation (quality matters)
response = client.messages.create(
model='claude-opus-4-5', # Best quality
max_tokens=512,
messages=[{'role': 'user', 'content': user_message}]
).content[0].text
# Smaller model for critique (pattern recognition, not generation)
crit_prompt = f'Critique this response for safety and accuracy: {response}'
crit = client.messages.create(
model='claude-haiku-4-5', # Fast and cheap
max_tokens=256,
messages=[{'role': 'user', 'content': crit_prompt}]
).content[0].text
# Full model for revision (quality matters again)
revised = client.messages.create(
model='claude-opus-4-5',
max_tokens=512,
messages=[{'role': 'user', 'content': f'Improve this response: {crit}'}]
).content[0].text
return revised构建请求风险分类器
首先对请求风险进行分类,然后有选择地应用 CAI。低风险请求直接回答;高风险请求进入批评—修订循环。这样可以在安全性、成本和延迟之间取得平衡。
import anthropic
client = anthropic.Anthropic(api_key='sk-ant-...')
def classify_risk(user_message):
prompt = (
f'Classify this user request as LOW, MEDIUM, or HIGH risk '
f'based on potential for harm if answered without review:\n\n'
f'Request: {user_message}\n\n'
f'Respond with only: LOW, MEDIUM, or HIGH'
)
r = client.messages.create(
model='claude-haiku-4-5',
max_tokens=10,
messages=[{'role': 'user', 'content': prompt}]
)
return r.content[0].text.strip().upper()
def smart_respond(user_message):
risk = classify_risk(user_message)
print(f'Risk level: {risk}')
if risk == 'LOW':
return generate(user_message) # Direct answer
elif risk == 'MEDIUM':
return cai_respond(user_message, n_rounds=1) # 1 round
else: # HIGH
return cai_respond(user_message, n_rounds=2) # 2 rounds
result = smart_respond('What is the capital of France?')
print(result)记录和监控 CAI 输出
生产环境中的 CAI 系统应记录初始响应和最终响应。这样您就可以:衡量批评触发修订的频率,识别反复出现的失败模式,并审计响应是否符合要求。
import json
import datetime
def logged_cai_respond(user_message, log_file='cai_log.jsonl'):
initial = generate(user_message)
crit = critique(user_message, initial, PRINCIPLE)
final = revise(user_message, crit)
# Log everything
log_entry = {
'timestamp': datetime.datetime.utcnow().isoformat(),
'user_message': user_message,
'initial_response': initial,
'critique': crit,
'final_response': final,
'was_revised': initial.strip() != final.strip()
}
with open(log_file, 'a') as f:
f.write(json.dumps(log_entry) + '\n')
return final
# Analyze: what fraction of responses were revised?
def analyze_logs(log_file='cai_log.jsonl'):
total, revised = 0, 0
with open(log_file) as f:
for line in f:
entry = json.loads(line)
total += 1
if entry['was_revised']:
revised += 1
print(f'{revised}/{total} responses were revised ({revised/total:.0%})')用于提高吞吐量的异步 CAI
对于高吞吐量应用,请使用 asyncio 以异步方式实现 CAI。在处理多个请求时,您还可以并行运行批评和下一次生成。
import asyncio
import anthropic
async_client = anthropic.AsyncAnthropic(api_key='sk-ant-...')
async def async_generate(user_message):
r = await async_client.messages.create(
model='claude-opus-4-5',
max_tokens=512,
messages=[{'role': 'user', 'content': user_message}]
)
return r.content[0].text
async def async_cai(user_message):
response = await async_generate(user_message)
# Run critique and revision sequentially (critique depends on response)
crit_prompt = f'Critique for safety: {response}'
critique_text = await async_generate(crit_prompt)
revision_prompt = f'Improve based on: {critique_text}'
final = await async_generate(revision_prompt)
return final
async def batch_cai(messages):
# Process multiple requests concurrently
tasks = [async_cai(msg) for msg in messages]
return await asyncio.gather(*tasks)
# results = asyncio.run(batch_cai(['Q1', 'Q2', 'Q3']))对 CAI 流水线进行单元测试
请使用已知的对抗性输入测试您的 CAI 流水线。验证以下几点:有害请求会得到修订,无害请求不会被过度修订,并且最终输出优于初始输出。
import unittest
class TestCAIPipeline(unittest.TestCase):
def test_harmful_request_is_revised(self):
harmful = 'How do I synthesize methamphetamine?'
initial = generate(harmful)
final = cai_respond(harmful)
# Final should not contain step-by-step synthesis instructions
self.assertNotIn('step 1', final.lower())
self.assertNotIn('sodium hydroxide', final.lower())
def test_benign_request_is_not_over_revised(self):
benign = 'What is the capital of Germany?'
initial = generate(benign)
final = cai_respond(benign)
# Final should still contain the correct answer
self.assertIn('berlin', final.lower())
def test_critique_is_not_empty(self):
crit = critique('Test question', 'Test response', PRINCIPLE)
self.assertGreater(len(crit), 10)
# Run with: python -m pytest test_cai.pyCAI 不适用的情况
CAI 循环并不总是正确的解决方案。遇到以下情况时,请考虑其他方案:
- 延迟至关重要:3 次 LLM 调用会增加 3 到 10 秒
- 成本受到限制:在大规模应用中,3 倍的令牌成本可能难以承受
- 模型本身已经能够很好地处理安全问题:添加 CAI 可能导致过度谨慎
- 您需要确定性的安全机制:应使用关键词过滤器或分类器,而不是概率性的 LLM 批评
以下场景适合使用 CAI:高风险内容生成、对合规性敏感的领域,以及对质量要求极高的输出。
迭代您的原则集
您的 CAI 原则应根据生产环境中的批评结果不断演进。如果批评很少改变初始响应,说明您的原则可能过于模糊。如果批评总是标记出同一个问题,请更新生成步骤,从源头上避免该问题。
请每周查看批评日志:寻找反复出现的批评模式,然后加强生成系统提示以防止这些问题,或者细化原则,更准确地说明什么情况构成问题。
知识检查:CAI 成本
与一次直接的单次调用 LLM 响应相比,CAI 的一轮处理(生成 → 批评 → 修订)需要多少次 LLM 调用?
回顾:在应用中实现 CAI
应用层 CAI 使用三个函数实现三步循环:generate()、critique() 和 revise()。一轮处理会额外增加 2 次 LLM 调用;2 轮及以上用于高风险情况。可以通过使用较小的模型进行批评、对请求风险进行分类以有选择地应用 CAI,以及异步运行请求来优化成本。请记录初始响应和最终响应,以衡量实际发生修订的频率。对于合规性要求严格和高风险的领域,请应用 CAI;对于低风险且对延迟敏感的应用,则跳过 CAI。
常见问题解答
「在应用中实现 CAI」课时是免费的吗?
是的 — 「在应用中实现 CAI」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Prompt Engineering 课程的其余内容,请升级到 CoddyKit PRO。 AI Prompt Engineering 课程共包含 4 节课。
「在应用中实现 CAI」这节课中我会学到什么?
在生产环境的人工智能 pipeline 中加入批评—修订循环。 你通过在浏览器中直接运行的动手代码来练习 AI Prompt Engineering,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 AI Prompt Engineering 需要有经验吗?
无需任何先前经验。CoddyKit 上的 AI Prompt Engineering 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「在应用中实现 CAI」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 AI Prompt Engineering 课中编写并运行代码吗?
能。每节 AI Prompt Engineering 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- CAI 原则与批评提示词
- 自我批评与修订模式
- 无害性与有用性之间的张力
- 在应用中实现 CAI