aboutsummaryrefslogtreecommitdiffstats
path: root/llamachat/providers.py
diff options
context:
space:
mode:
Diffstat (limited to 'llamachat/providers.py')
-rw-r--r--llamachat/providers.py22
1 files changed, 22 insertions, 0 deletions
diff --git a/llamachat/providers.py b/llamachat/providers.py
index a8b2350..23ad081 100644
--- a/llamachat/providers.py
+++ b/llamachat/providers.py
@@ -49,6 +49,12 @@ class Provider:
# Provider-specific reasoning token budget. Currently SiliconFlow only;
# ignored when unset so other endpoints do not receive an unknown key.
thinking_budget: int | None = None
+ # Replay each assistant turn's reasoning_content on the next request.
+ # Interleaved-thinking providers (DeepSeek, SiliconFlow's GLM-4.7+) reject
+ # a tools request whose prior assistant turns omit it. Off by default:
+ # replaying thinking inflates context and the input bill for providers
+ # that neither need nor want it.
+ replay_reasoning: bool = False
@property
def is_local(self) -> bool:
@@ -189,6 +195,7 @@ def parse(values: dict, warnings: list[str] | None = None) -> dict[str, Provider
price_in=_number(entry.get("price_in"), float),
price_out=_number(entry.get("price_out"), float),
thinking_budget=_number(entry.get("thinking_budget"), int),
+ replay_reasoning=bool(entry.get("replay_reasoning", False)),
)
return out
@@ -220,6 +227,21 @@ def split(model_id: str, table: dict[str, Provider]) -> tuple[str, str]:
return LOCAL, model_id
+def replays_reasoning(model_id: str, table: dict[str, Provider], search_enabled: bool) -> bool:
+ """Whether a request to this model must replay reasoning_content.
+
+ Only true when search is enabled, because that is the only time the app
+ sends a `tools` key — the condition under which interleaved-thinking
+ providers demand the reasoning back. The caller still checks that a given
+ row has non-empty reasoning; a non-reasoning model has nothing to replay.
+ """
+ if not search_enabled:
+ return False
+ name, _ = split(model_id, table)
+ provider = table.get(name)
+ return bool(provider and provider.replay_reasoning)
+
+
def apply_filter(provider: Provider, listed: list[str]) -> list[str]:
"""Keep models matching any of the provider's substrings.