Skip to content

Commit 670f9ab

Browse files
Add examples and tests for Anthropic prompt caching in TinyAgent
This commit introduces a new example script demonstrating the Anthropic prompt caching feature, which optimizes cache control for large messages in Claude models. Additionally, a comprehensive suite of tests is added to validate the functionality of the caching mechanism, including integration tests, control tests, and verification of message modifications. The tests ensure that the caching behavior works as expected and that the system maintains compatibility with various message formats and scenarios.
1 parent 307e7f2 commit 670f9ab

14 files changed

Lines changed: 2702 additions & 0 deletions
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
"""
2+
Anthropic Prompt Cache Example for TinyAgent
3+
4+
This example demonstrates the Anthropic prompt caching feature that automatically
5+
adds cache control to large messages for Claude models.
6+
"""
7+
8+
import asyncio
9+
import logging
10+
import os
11+
12+
from tinyagent import TinyAgent
13+
from tinyagent.hooks import anthropic_prompt_cache
14+
15+
# Setup logging to see what's happening
16+
logging.basicConfig(level=logging.INFO)
17+
logger = logging.getLogger(__name__)
18+
19+
20+
async def basic_example():
21+
"""Basic example showing Anthropic prompt cache callback."""
22+
logger.info("=== Anthropic Prompt Cache Example ===")
23+
24+
# Create agent with Claude model
25+
agent = TinyAgent(
26+
model="claude-3-5-sonnet-20241022",
27+
system_prompt="You are a helpful assistant.",
28+
temperature=0.1
29+
)
30+
31+
# Add Anthropic prompt cache callback - that's it!
32+
cache_callback = anthropic_prompt_cache()
33+
agent.add_callback(cache_callback)
34+
35+
try:
36+
# Test with a short message (won't trigger caching)
37+
logger.info("--- Short Message Test ---")
38+
short_response = await agent.run("Hello! How are you?")
39+
logger.info(f"Short response: {short_response[:100]}...")
40+
41+
# Test with a long message (will trigger caching)
42+
logger.info("--- Long Message Test ---")
43+
long_prompt = "Please analyze the following text in detail: " + "This is sample content for analysis. " * 100
44+
long_response = await agent.run(long_prompt)
45+
logger.info(f"Long response: {long_response[:100]}...")
46+
logger.info("Cache control should have been added to the long message.")
47+
48+
# Test with follow-up (might benefit from caching)
49+
follow_up = await agent.run("Can you summarize your previous analysis?")
50+
logger.info(f"Follow-up response: {follow_up[:100]}...")
51+
52+
finally:
53+
await agent.close()
54+
55+
56+
async def code_analysis_example():
57+
"""Example with code analysis that benefits from caching."""
58+
logger.info("=== Code Analysis Example ===")
59+
60+
agent = TinyAgent(
61+
model="claude-3-5-sonnet-20241022",
62+
system_prompt="You are a code analysis expert.",
63+
temperature=0.1
64+
)
65+
66+
# Add Anthropic prompt cache callback
67+
cache_callback = anthropic_prompt_cache()
68+
agent.add_callback(cache_callback)
69+
70+
try:
71+
# Simulate analyzing a large codebase
72+
large_code = '''
73+
def process_data(data):
74+
"""Process incoming data."""
75+
results = []
76+
for item in data:
77+
if validate_item(item):
78+
processed = transform_item(item)
79+
results.append(processed)
80+
return results
81+
82+
def validate_item(item):
83+
"""Validate a single item."""
84+
return item is not None and len(item) > 0
85+
86+
def transform_item(item):
87+
"""Transform a single item."""
88+
return item.upper().strip()
89+
''' * 50 # Make it large enough to trigger caching
90+
91+
prompt = f"Please analyze this Python code and suggest improvements:\n\n{large_code}"
92+
93+
response = await agent.run(prompt)
94+
logger.info(f"Code analysis response: {len(response)} characters")
95+
logger.info("Large code analysis should have triggered caching.")
96+
97+
# Follow-up question that might benefit from cache
98+
follow_up = await agent.run("What are the main security concerns with this code?")
99+
logger.info(f"Follow-up: {follow_up[:100]}...")
100+
101+
finally:
102+
await agent.close()
103+
104+
105+
async def claude_4_example():
106+
"""Example showing Claude 4 model support."""
107+
logger.info("=== Claude 4 Model Example ===")
108+
109+
# Example with Claude 4 model
110+
agent = TinyAgent(
111+
model="claude-sonnet-4-20250514", # Actual Claude 4 model
112+
system_prompt="You are a helpful assistant.",
113+
temperature=0.1
114+
)
115+
116+
# Add cache callback (will work with Claude 4 models)
117+
cache_callback = anthropic_prompt_cache()
118+
agent.add_callback(cache_callback)
119+
120+
try:
121+
long_prompt = "Explain machine learning in detail: " + "Please be thorough. " * 100
122+
response = await agent.run(long_prompt)
123+
logger.info(f"Claude 4 response: {response[:100]}...")
124+
logger.info("Cache control should be added for Claude 4 models.")
125+
126+
except Exception as e:
127+
logger.info(f"Claude 4 example failed (model may not be available yet): {e}")
128+
finally:
129+
await agent.close()
130+
131+
132+
async def main():
133+
"""Run all examples."""
134+
if not os.getenv("ANTHROPIC_API_KEY"):
135+
logger.warning("ANTHROPIC_API_KEY not set. Set it to see caching in action.")
136+
logger.info("Example: export ANTHROPIC_API_KEY='your-key-here'")
137+
return
138+
139+
try:
140+
await basic_example()
141+
await asyncio.sleep(1)
142+
143+
await code_analysis_example()
144+
await asyncio.sleep(1)
145+
146+
await claude_4_example()
147+
148+
except Exception as e:
149+
logger.error(f"Error in examples: {e}")
150+
151+
logger.info("Anthropic Prompt Cache Examples Complete")
152+
153+
154+
if __name__ == "__main__":
155+
asyncio.run(main())

0 commit comments

Comments
 (0)