Complete local hybrid search and improve agent reliability
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
from collections.abc import AsyncIterator
|
||||
@@ -28,6 +29,10 @@ class ModelProvider(Protocol):
|
||||
|
||||
async def list_models(self) -> list[str]: ...
|
||||
|
||||
async def describe_models(
|
||||
self, model_names: list[str]
|
||||
) -> dict[str, dict[str, Any]]: ...
|
||||
|
||||
|
||||
class OllamaProvider:
|
||||
name = "ollama"
|
||||
@@ -62,6 +67,11 @@ class OllamaProvider:
|
||||
status_code=502,
|
||||
detail=f"خطأ من خادم النموذج المحلي: {detail}",
|
||||
) from exc
|
||||
except httpx.TimeoutException as exc:
|
||||
raise HTTPException(
|
||||
status_code=504,
|
||||
detail="انتهت مهلة انتظار خادم النموذج المحلي.",
|
||||
) from exc
|
||||
except httpx.RequestError as exc:
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
@@ -125,6 +135,63 @@ class OllamaProvider:
|
||||
if isinstance(item, dict) and item.get("name")
|
||||
]
|
||||
|
||||
async def describe_models(
|
||||
self, model_names: list[str]
|
||||
) -> dict[str, dict[str, Any]]:
|
||||
"""Read capability metadata advertised by the installed Ollama models."""
|
||||
ollama_base = (
|
||||
self.base_url[:-3] if self.base_url.endswith("/v1") else self.base_url
|
||||
)
|
||||
capability_order = [
|
||||
"completion",
|
||||
"vision",
|
||||
"audio",
|
||||
"tools",
|
||||
"thinking",
|
||||
"embedding",
|
||||
]
|
||||
semaphore = asyncio.Semaphore(4)
|
||||
|
||||
async def describe(client: httpx.AsyncClient, model_name: str):
|
||||
async with semaphore:
|
||||
try:
|
||||
response = await client.post(
|
||||
f"{ollama_base}/api/show",
|
||||
json={"model": model_name, "verbose": False},
|
||||
)
|
||||
response.raise_for_status()
|
||||
payload = response.json()
|
||||
raw = (
|
||||
payload.get("capabilities")
|
||||
if isinstance(payload, dict)
|
||||
else None
|
||||
)
|
||||
verified = isinstance(raw, list)
|
||||
return model_name, {
|
||||
"verified": verified,
|
||||
"capabilities": [
|
||||
capability
|
||||
for capability in capability_order
|
||||
if capability in raw
|
||||
]
|
||||
if verified
|
||||
else [],
|
||||
}
|
||||
except (httpx.HTTPError, ValueError, TypeError):
|
||||
return model_name, {"verified": False, "capabilities": []}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
described = await asyncio.gather(
|
||||
*(describe(client, name) for name in model_names)
|
||||
)
|
||||
return dict(described)
|
||||
except httpx.HTTPError:
|
||||
return {
|
||||
name: {"verified": False, "capabilities": []}
|
||||
for name in model_names
|
||||
}
|
||||
|
||||
|
||||
def get_model_provider() -> ModelProvider:
|
||||
provider_name = os.getenv("MODEL_PROVIDER", "ollama").strip().lower()
|
||||
|
||||
Reference in New Issue
Block a user