| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- """
- 测试多轮对话的 Prompt Caching
- """
- import asyncio
- import os
- import sys
- from pathlib import Path
- sys.path.insert(0, str(Path(__file__).parent.parent.parent))
- from dotenv import load_dotenv
- load_dotenv()
- from agent.core.runner import AgentRunner, RunConfig
- from agent.trace import FileSystemTraceStore, Trace, Message
- from agent.llm import create_openrouter_llm_call
- async def main():
- print("=" * 60)
- print("测试多轮对话 Prompt Caching")
- print("=" * 60)
- print()
- base_dir = Path(__file__).parent
- project_root = base_dir.parent.parent
- trace_dir = project_root / ".trace"
- runner = AgentRunner(
- trace_store=FileSystemTraceStore(base_path=str(trace_dir)),
- llm_call=create_openrouter_llm_call(model="anthropic/claude-sonnet-4.5"),
- debug=True
- )
- # 超长 system prompt 确保 >1024 tokens
- system_prompt = """你是一个专业的 AI 助手,专注于帮助用户解决技术问题。
- ## 核心能力
- - 代码分析和生成
- - 问题解决和调试
- - 技术文档编写
- - 架构设计建议
- - 性能优化建议
- - 安全审计
- ## 工作原则
- 1. 准确性优先:确保提供的信息和代码是正确的
- 2. 清晰表达:用简洁明了的语言解释复杂概念
- 3. 实用导向:提供可直接使用的解决方案
- 4. 持续学习:根据反馈不断改进
- 5. 安全意识:始终考虑安全性和最佳实践
- 6. 性能考虑:提供高效的解决方案
- ## 技术栈
- - 编程语言:Python, JavaScript, TypeScript, Go, Rust, Java
- - 前端框架:React, Vue, Angular, Svelte
- - 后端框架:Node.js, Django, Flask, FastAPI, Spring Boot
- - 数据库:PostgreSQL, MongoDB, Redis, MySQL, Elasticsearch
- - 云平台:AWS, GCP, Azure
- - DevOps:Docker, Kubernetes, CI/CD, Terraform
- - 机器学习:TensorFlow, PyTorch, scikit-learn
- ## 响应格式
- - 提供清晰的步骤说明
- - 包含代码示例
- - 解释关键概念
- - 指出潜在问题
- - 给出最佳实践建议
- 这是一个足够长的 system prompt,用于测试 Anthropic Prompt Caching 功能。
- 缓存需要至少 1024 tokens 才能生效,所以我们需要让这个 prompt 足够长。
- """ * 5 # 重复 5 次确保足够长
- messages = [
- {"role": "user", "content": "请用一句话介绍 Python"}
- ]
- print("开始多轮对话测试...")
- print("-" * 60)
- trace_id = None
- iteration = 0
- async for item in runner.run(
- messages=messages,
- config=RunConfig(
- system_prompt=system_prompt,
- model="anthropic/claude-sonnet-4.5",
- temperature=0.3,
- max_iterations=5, # 多轮对话
- enable_prompt_caching=True,
- name="多轮缓存测试"
- )
- ):
- if isinstance(item, Trace):
- trace_id = item.trace_id
- if item.status == "completed":
- print(f"\n✓ Trace 完成")
- print(f" Total messages: {item.total_messages}")
- print(f" Total tokens: {item.total_tokens}")
- print(f" Total cache creation: {item.total_cache_creation_tokens}")
- print(f" Total cache read: {item.total_cache_read_tokens}")
- print(f" Total cost: ${item.total_cost:.6f}")
- elif isinstance(item, Message):
- if item.role == "assistant":
- iteration += 1
- print(f"\n[Iteration {iteration}]")
- print(f" Prompt tokens: {item.prompt_tokens}")
- print(f" Completion tokens: {item.completion_tokens}")
- print(f" Cache creation: {item.cache_creation_tokens}")
- print(f" Cache read: {item.cache_read_tokens}")
- print(f" Cost: ${item.cost:.6f}")
- content = item.content
- if isinstance(content, dict):
- text = content.get("text", "")
- tool_calls = content.get("tool_calls")
- if text and not tool_calls:
- preview = text[:80] + "..." if len(text) > 80 else text
- print(f" Response: {preview}")
- if tool_calls:
- print(f" Tool calls: {len(tool_calls)}")
- print()
- print("=" * 60)
- print("测试完成")
- print("=" * 60)
- print()
- if trace_id:
- print("分析:")
- print("- 第 1 次调用:应该有 cache_creation_tokens > 0(创建缓存)")
- print("- 第 2+ 次调用:应该有 cache_read_tokens > 0(命中缓存)")
- print(f"\nTrace ID: {trace_id}")
- if __name__ == "__main__":
- asyncio.run(main())
|