ducklm/app/models/async_adapters.py

58 lines
1.7 KiB
Python

from __future__ import annotations
import asyncio
from typing import Any, AsyncIterator
from app.models.orchestrator import OrchestratorAdapter as SyncOrchestrator
class AsyncOrchestratorAdapter:
"""Async wrapper for orchestrator - runs in executor to avoid blocking event loop."""
def __init__(self, sync_adapter: SyncOrchestrator) -> None:
self._sync = sync_adapter
async def generate(self, prompt: str, max_tokens: int | None = None) -> str:
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
None,
lambda: self._sync.generate(prompt, max_tokens)
)
async def stream(self, prompt: str, max_tokens: int | None = None) -> AsyncIterator[str]:
loop = asyncio.get_event_loop()
async def gen():
return list(self._sync.stream(prompt, max_tokens))
result = await loop.run_in_executor(None, gen)
for chunk in result:
yield chunk
class AsyncCoderAdapter:
"""Async wrapper for coder."""
def __init__(self, sync_adapter) -> None:
self._sync = sync_adapter
async def generate(self, prompt: str, max_tokens: int | None = None) -> str:
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
None,
lambda: self._sync.generate(prompt, max_tokens)
)
class AsyncCriticAdapter:
"""Async wrapper for critic."""
def __init__(self, sync_adapter) -> None:
self._sync = sync_adapter
async def generate(self, prompt: str, max_tokens: int | None = None) -> str:
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
None,
lambda: self._sync.generate(prompt, max_tokens)
)