mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-22 06:28:11 +02:00
Ajoute un interrupteur « Mode réflexion » (think) pour les modèles thinking
Certains modèles « thinking » ne renvoyaient que du raisonnement, sans reponse finale -> erreur. Nouvel interrupteur global `think` (Reglages > Generation) : - think=false envoie `think:false` a Ollama pour desactiver le raisonnement - repli automatique si le modele refuse le parametre (does not support thinking) - message d'erreur mis a jour pour pointer vers l'interrupteur Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
b4fc8cee3d
commit
5c1b92daa3
7 files changed
+41
-3
No files matched your search
+21
-3
@@ -44,6 +44,12 @@ def _tools_not_supported(exc: OllamaError) -> bool:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _thinking_not_supported(exc: OllamaError) -> bool:
|
||||||
|
"""Le modèle (ou son template) refuse le paramètre ``think``."""
|
||||||
|
message = str(exc).lower()
|
||||||
|
return "does not support thinking" in message or "thinking is not supported" in message
|
||||||
|
|
||||||
|
|
||||||
def _invalid_tool_arguments(exc: OllamaError) -> bool:
|
def _invalid_tool_arguments(exc: OllamaError) -> bool:
|
||||||
message = str(exc).lower()
|
message = str(exc).lower()
|
||||||
return (
|
return (
|
||||||
@@ -71,6 +77,7 @@ async def run_agent(
|
|||||||
options: dict | None = None,
|
options: dict | None = None,
|
||||||
enabled_tools: list[str] | None = None,
|
enabled_tools: list[str] | None = None,
|
||||||
confirm_shell: bool = True,
|
confirm_shell: bool = True,
|
||||||
|
think: bool = True,
|
||||||
) -> AsyncIterator[dict]:
|
) -> AsyncIterator[dict]:
|
||||||
# enabled_tools=None -> tous les outils ; liste vide -> aucun outil.
|
# enabled_tools=None -> tous les outils ; liste vide -> aucun outil.
|
||||||
if enabled_tools is None:
|
if enabled_tools is None:
|
||||||
@@ -88,6 +95,9 @@ async def run_agent(
|
|||||||
tool_fallback_used = False
|
tool_fallback_used = False
|
||||||
tool_repair_attempts = 0
|
tool_repair_attempts = 0
|
||||||
request_options = dict(options or {})
|
request_options = dict(options or {})
|
||||||
|
# On n'envoie ``think`` que pour le DÉSACTIVER (False) ; laissé à None, le
|
||||||
|
# modèle garde son comportement par défaut. Repli si le modèle le refuse.
|
||||||
|
request_think: bool | None = None if think else False
|
||||||
|
|
||||||
# Métriques cumulées sur tous les appels Ollama du tour agentique : Ollama
|
# Métriques cumulées sur tous les appels Ollama du tour agentique : Ollama
|
||||||
# les renvoie dans le chunk final (done=true) de chaque génération.
|
# les renvoie dans le chunk final (done=true) de chaque génération.
|
||||||
@@ -114,6 +124,7 @@ async def run_agent(
|
|||||||
convo,
|
convo,
|
||||||
tools=active_tools,
|
tools=active_tools,
|
||||||
options=request_options,
|
options=request_options,
|
||||||
|
think=request_think,
|
||||||
stream=True,
|
stream=True,
|
||||||
):
|
):
|
||||||
msg = chunk.get("message", {})
|
msg = chunk.get("message", {})
|
||||||
@@ -191,6 +202,11 @@ async def run_agent(
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
if request_think is not None and _thinking_not_supported(exc):
|
||||||
|
# Le modèle n'accepte pas qu'on désactive sa réflexion :
|
||||||
|
# on retire le paramètre et on relance.
|
||||||
|
request_think = None
|
||||||
|
continue
|
||||||
raise
|
raise
|
||||||
|
|
||||||
assistant_turn: dict = {"role": "assistant", "content": content_buf}
|
assistant_turn: dict = {"role": "assistant", "content": content_buf}
|
||||||
@@ -270,7 +286,8 @@ async def run_agent(
|
|||||||
# Laisse le modèle conclure son tour (message d'attente).
|
# Laisse le modèle conclure son tour (message d'attente).
|
||||||
final_chunk = ""
|
final_chunk = ""
|
||||||
async for chunk in ollama.chat(
|
async for chunk in ollama.chat(
|
||||||
model, convo, options=request_options, stream=True
|
model, convo, options=request_options,
|
||||||
|
think=request_think, stream=True
|
||||||
):
|
):
|
||||||
tok = chunk.get("message", {}).get("content", "")
|
tok = chunk.get("message", {}).get("content", "")
|
||||||
if tok:
|
if tok:
|
||||||
@@ -299,8 +316,9 @@ async def run_agent(
|
|||||||
yield {
|
yield {
|
||||||
"type": "error",
|
"type": "error",
|
||||||
"message": (
|
"message": (
|
||||||
"Le modèle a terminé sans renvoyer de texte. Essayez un modèle "
|
"Le modèle a terminé sans renvoyer de texte (il n'a produit que "
|
||||||
"de chat récent ou désactivez son mode de réflexion avancée."
|
"du raisonnement). Désactive « Mode réflexion » dans les Réglages, "
|
||||||
|
"ou essaie un modèle de chat plus récent."
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ DEFAULT_CONFIG: dict = {
|
|||||||
"tools": dict(DEFAULT_TOOL_STATE),
|
"tools": dict(DEFAULT_TOOL_STATE),
|
||||||
# Demander une validation utilisateur avant toute commande shell.
|
# Demander une validation utilisateur avant toute commande shell.
|
||||||
"confirm_shell": True,
|
"confirm_shell": True,
|
||||||
|
# Mode réflexion des modèles « thinking ». Désactiver (False) évite qu'un
|
||||||
|
# modèle ne renvoie que du raisonnement sans réponse finale.
|
||||||
|
"think": True,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ class OllamaClient:
|
|||||||
*,
|
*,
|
||||||
tools: list[dict] | None = None,
|
tools: list[dict] | None = None,
|
||||||
options: dict | None = None,
|
options: dict | None = None,
|
||||||
|
think: bool | None = None,
|
||||||
stream: bool = True,
|
stream: bool = True,
|
||||||
) -> AsyncIterator[dict]:
|
) -> AsyncIterator[dict]:
|
||||||
"""Conversation avec le modèle, en streaming token par token."""
|
"""Conversation avec le modèle, en streaming token par token."""
|
||||||
@@ -114,6 +115,9 @@ class OllamaClient:
|
|||||||
payload["tools"] = tools
|
payload["tools"] = tools
|
||||||
if options:
|
if options:
|
||||||
payload["options"] = options
|
payload["options"] = options
|
||||||
|
# think=False désactive le raisonnement des modèles « thinking ».
|
||||||
|
if think is not None:
|
||||||
|
payload["think"] = think
|
||||||
|
|
||||||
async with httpx.AsyncClient(
|
async with httpx.AsyncClient(
|
||||||
timeout=_STREAM_TIMEOUT, follow_redirects=True
|
timeout=_STREAM_TIMEOUT, follow_redirects=True
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ async def chat(req: ChatRequest) -> StreamingResponse:
|
|||||||
options=agent_config.ollama_options(cfg),
|
options=agent_config.ollama_options(cfg),
|
||||||
enabled_tools=agent_config.enabled_tool_names(cfg),
|
enabled_tools=agent_config.enabled_tool_names(cfg),
|
||||||
confirm_shell=cfg.get("confirm_shell", True),
|
confirm_shell=cfg.get("confirm_shell", True),
|
||||||
|
think=cfg.get("think", True),
|
||||||
):
|
):
|
||||||
await queue.put(event)
|
await queue.put(event)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class ConfigPatch(BaseModel):
|
|||||||
num_batch: int | None = None
|
num_batch: int | None = None
|
||||||
tools: dict[str, bool] | None = None
|
tools: dict[str, bool] | None = None
|
||||||
confirm_shell: bool | None = None
|
confirm_shell: bool | None = None
|
||||||
|
think: bool | None = None
|
||||||
|
|
||||||
|
|
||||||
@router.get("")
|
@router.get("")
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ export interface AgentConfig {
|
|||||||
num_batch: number;
|
num_batch: number;
|
||||||
tools: Record<string, boolean>;
|
tools: Record<string, boolean>;
|
||||||
confirm_shell: boolean;
|
confirm_shell: boolean;
|
||||||
|
think: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function runShell(
|
export async function runShell(
|
||||||
|
|||||||
@@ -289,6 +289,16 @@ export function SettingsView() {
|
|||||||
onChange={(v) => set("num_batch", Math.round(v))}
|
onChange={(v) => set("num_batch", Math.round(v))}
|
||||||
last
|
last
|
||||||
/>
|
/>
|
||||||
|
<div className="mt-4 flex items-center gap-3 border-2 border-line bg-base px-3 py-2.5">
|
||||||
|
<div className="flex-1">
|
||||||
|
<div className="text-[14px] text-ink">Mode réflexion</div>
|
||||||
|
<div className="text-[12px] text-muted-2">
|
||||||
|
Désactive si le modèle ne renvoie que du raisonnement sans
|
||||||
|
réponse.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Toggle on={draft.think} onClick={() => set("think", !draft.think)} />
|
||||||
|
</div>
|
||||||
<div className="mt-3 border-2 border-line bg-card-soft px-3 py-2 text-[12px] leading-relaxed text-muted-2">
|
<div className="mt-3 border-2 border-line bg-card-soft px-3 py-2 text-[12px] leading-relaxed text-muted-2">
|
||||||
La précision KV (<code>f16</code>/<code>q8_0</code>) est un
|
La précision KV (<code>f16</code>/<code>q8_0</code>) est un
|
||||||
réglage global du serveur Ollama et nécessite son redémarrage.
|
réglage global du serveur Ollama et nécessite son redémarrage.
|
||||||
|
|||||||
Reference in new issue
Block a user