- matrix-gateway: POST /internal/matrix/presence/online endpoint - usePresenceHeartbeat hook with activity tracking - Auto away after 5 min inactivity - Offline on page close/visibility change - Integrated in MatrixChatRoom component
76 lines
2.3 KiB
Python
76 lines
2.3 KiB
Python
import httpx
|
|
import time
|
|
from models import ChatMessage, LLMResponse, Usage, ProviderConfig
|
|
|
|
class OpenAIProvider:
|
|
"""OpenAI API provider"""
|
|
|
|
def __init__(self, config: ProviderConfig):
|
|
self.config = config
|
|
self.client = httpx.AsyncClient(
|
|
base_url=config.base_url,
|
|
timeout=config.timeout,
|
|
headers={
|
|
"Authorization": f"Bearer {config.api_key}",
|
|
"Content-Type": "application/json"
|
|
} if config.api_key else {}
|
|
)
|
|
|
|
async def chat(
|
|
self,
|
|
messages: list[ChatMessage],
|
|
model_name: str,
|
|
max_tokens: int | None = None,
|
|
temperature: float = 0.7,
|
|
top_p: float = 1.0,
|
|
**kwargs
|
|
) -> LLMResponse:
|
|
"""Call OpenAI Chat Completions API"""
|
|
start_time = time.time()
|
|
|
|
payload = {
|
|
"model": model_name,
|
|
"messages": [{"role": m.role, "content": m.content} for m in messages],
|
|
"temperature": temperature,
|
|
"top_p": top_p
|
|
}
|
|
|
|
if max_tokens:
|
|
payload["max_tokens"] = max_tokens
|
|
|
|
try:
|
|
response = await self.client.post(
|
|
"/chat/completions",
|
|
json=payload
|
|
)
|
|
response.raise_for_status()
|
|
data = response.json()
|
|
|
|
latency_ms = (time.time() - start_time) * 1000
|
|
|
|
return LLMResponse(
|
|
content=data["choices"][0]["message"]["content"],
|
|
usage=Usage(
|
|
prompt_tokens=data["usage"]["prompt_tokens"],
|
|
completion_tokens=data["usage"]["completion_tokens"],
|
|
total_tokens=data["usage"]["total_tokens"]
|
|
),
|
|
provider="openai",
|
|
model_resolved=model_name,
|
|
latency_ms=latency_ms,
|
|
cached=False
|
|
)
|
|
|
|
except httpx.HTTPStatusError as e:
|
|
raise Exception(f"OpenAI API error: {e.response.status_code} - {e.response.text}")
|
|
except Exception as e:
|
|
raise Exception(f"OpenAI provider error: {str(e)}")
|
|
|
|
async def close(self):
|
|
"""Close HTTP client"""
|
|
await self.client.aclose()
|
|
|
|
|
|
|
|
|