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())