Async Examples¶
Async/await examples for concurrent API operations:
1#!/usr/bin/env python
2"""
332 Async API - Concurrent Requests
4
5Learn how to use async/await for concurrent API calls.
6This is useful for making multiple requests simultaneously.
7
8Level: Advanced Feature
9"""
10
11import asyncio
12import time
13
14from config_loader import get_chat_config, parse_args
15
16from lexilux import Chat
17
18
19async def main():
20 """Demonstrate async API usage."""
21 args = parse_args()
22 try:
23 config = get_chat_config(config_path=args.config)
24 except (FileNotFoundError, KeyError) as e:
25 print(f"Configuration error: {e}")
26 print("\nUsing placeholder values. Please configure test_endpoints.json")
27 config = {
28 "base_url": "https://api.example.com/v1",
29 "api_key": "your-api-key",
30 "model": "gpt-4",
31 }
32
33 # Example 1: Basic async call
34 print("=" * 50)
35 print("Example 1: Basic Async Call")
36 print("=" * 50)
37
38 chat = Chat(**config)
39
40 print("Calling chat asynchronously...")
41 result = await chat.a("Hello, async world!")
42 print(f"Response: {result.text}")
43 print(f"Tokens: {result.usage.total_tokens}\n")
44
45 # Example 2: Concurrent requests
46 print("=" * 50)
47 print("Example 2: Concurrent Requests (much faster!)")
48 print("=" * 50)
49
50 questions = [
51 "What is Python?",
52 "What is JavaScript?",
53 "What is Rust?",
54 "What is Go?",
55 ]
56
57 # Sequential timing (for comparison)
58 print("Sequential execution (for comparison):")
59 start = time.time()
60 for q in questions:
61 result = await chat.a(q)
62 print(f" - {result.text[:50]}...")
63 sequential_time = time.time() - start
64 print(f"Time: {sequential_time:.2f}s\n")
65
66 # Concurrent execution
67 print("Concurrent execution:")
68 start = time.time()
69
70 tasks = [chat.a(q) for q in questions]
71 results = await asyncio.gather(*tasks)
72
73 for result in results:
74 print(f" - {result.text[:50]}...")
75
76 concurrent_time = time.time() - start
77 print(f"Time: {concurrent_time:.2f}s")
78 print(f"Speedup: {sequential_time / concurrent_time:.1f}x faster!\n")
79
80 # Example 3: Async streaming
81 print("=" * 50)
82 print("Example 3: Async Streaming")
83 print("=" * 50)
84
85 print("Streaming response asynchronously:\n")
86
87 full_response = ""
88 async for chunk in chat.astream("Tell me a short joke"):
89 if chunk.delta:
90 full_response += chunk.delta
91 print(chunk.delta, end="", flush=True)
92 if chunk.done:
93 print(f"\n\nTokens: {chunk.usage.total_tokens}\n")
94
95 # Example 4: Parallel streaming
96 print("=" * 50)
97 print("Example 4: Parallel Streaming")
98 print("=" * 50)
99
100 async def stream_and_collect(prompt: str) -> str:
101 """Stream a response and collect the full text."""
102 full = ""
103 async for chunk in chat.astream(prompt):
104 if chunk.delta:
105 full += chunk.delta
106 return full
107
108 prompts = [
109 "Tell me a joke",
110 "Give me a quote",
111 "Say something wise",
112 ]
113
114 print("Streaming multiple requests in parallel:\n")
115 start = time.time()
116
117 tasks = [stream_and_collect(p) for p in prompts]
118 results = await asyncio.gather(*tasks)
119
120 for prompt, result in zip(prompts, results):
121 print(f"'{prompt}' → {result[:50]}...")
122
123 print(f"\nTime: {time.time() - start:.2f}s\n")
124
125 # Example 5: Rate limiting with async
126 print("=" * 50)
127 print("Example 5: Rate Limiting (async semaphore)")
128 print("=" * 50)
129
130 semaphore = asyncio.Semaphore(2) # Max 2 concurrent requests
131
132 async def limited_chat(prompt: str) -> str:
133 """Chat with rate limiting."""
134 async with semaphore:
135 result = await chat.a(prompt)
136 return result.text
137
138 many_prompts = [f"Question {i}" for i in range(5)]
139
140 print(f"Processing {len(many_prompts)} requests with max 2 concurrent:")
141 start = time.time()
142
143 tasks = [limited_chat(p) for p in many_prompts]
144 results = await asyncio.gather(*tasks)
145
146 for i, result in enumerate(results, 1):
147 print(f" {i}. {result[:50]}...")
148
149 print(f"\nTime: {time.time() - start:.2f}s")
150
151
152if __name__ == "__main__":
153 # Run the async main function
154 asyncio.run(main())