openher / providers /llm /client.py
kellyxiaowei's picture
Deploy OpenHer Gradio Space โ€” gemma-4-E4B served on Modal
dff25f7 verified
Raw
History Blame Contribute Delete
2.85 kB
"""
LLM Client โ€” Facade over core.providers.llm.
ไฟ็•™ๅŽŸๆœ‰ API ้ข (LLMClient, ChatMessage, ChatResponse)๏ผŒ
ๅ†…้ƒจๅง”ๆ‰˜ๅˆฐ providers.registry.get_llm() ๅˆ›ๅปบ็š„ providerใ€‚
ๆ‰€ๆœ‰ไธŠๅฑ‚่ฐƒ็”จ (chat_agent, critic, main.py) ๆ— ้œ€ๆ”นๅŠจใ€‚
"""
from __future__ import annotations
from typing import AsyncIterator, Optional
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
# Re-export public types (facade ๅ…ผๅฎนๅฅ‘็บฆ)
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
from providers.llm.base import ChatMessage, ChatResponse # noqa: F401
class LLMClient:
"""
Async LLM client for OpenHer.
Thin facade โ€” ๅง”ๆ‰˜ๅˆฐ core.providers.llm ็š„ๅ…ทไฝ“ provider ๅฎž็Žฐใ€‚
Constructor ็ญพๅไธๅ˜๏ผŒๆ‰€ๆœ‰่ฐƒ็”จๆ–นๆ— ้œ€ๆ”นๅŠจใ€‚
Usage:
client = LLMClient(provider="dashscope", model="qwen-max")
response = await client.chat([
ChatMessage("system", "You are a companion..."),
ChatMessage("user", "ไฝ ๅฅฝๅ‘€"),
])
print(response.content)
"""
def __init__(
self,
provider: str = "dashscope",
model: Optional[str] = None,
api_key: Optional[str] = None,
base_url: Optional[str] = None,
temperature: float = 0.92,
max_tokens: int = 1024,
):
from providers.registry import get_llm
self.provider = provider
self._impl = get_llm(
provider=provider,
model=model,
api_key=api_key,
base_url=base_url,
temperature=temperature,
max_tokens=max_tokens,
)
# Expose model name for observability (main.py prints it)
self.model = self._impl.model
print(f"โœ“ LLM ๅฎขๆˆท็ซฏ: {self.model} ({self.provider}) [async]")
async def chat(
self,
messages: list[ChatMessage],
temperature: Optional[float] = None,
max_tokens: Optional[int] = None,
tools: Optional[list[dict]] = None,
tool_choice: Optional[str] = None,
) -> ChatResponse:
"""Send a chat request and get a response (async)."""
return await self._impl.chat(messages, temperature, max_tokens, tools, tool_choice)
async def chat_stream(
self,
messages: list[ChatMessage],
temperature: Optional[float] = None,
max_tokens: Optional[int] = None,
) -> AsyncIterator[str]:
"""Stream a chat response, yielding content chunks (async)."""
async for chunk in self._impl.chat_stream(messages, temperature, max_tokens):
yield chunk