Set the search summary model from the settings panel

Summarizing web search results falls back to DEFAULT_MODEL, so a local Ollama
model ends up doing it and the call can fail — which surfaces only as
"保存できる要約なし" in the chat. Make SEARCH_SUMMARY_MODEL settable at runtime:
add it to the settings allowlist and read it from os.environ on each call
(knowledge._summary_model), the way LOCAL_KB_EMBEDDING_MODEL already works.
Importing it as a config constant would keep the old value until a restart.

Show the current value of the settings that are not secrets. A model name
rendered as ••••qwen3 gives no way to tell what is in effect, so the store now
marks those keys (NON_SECRET_KEYS) and returns them unmasked; the API field is
renamed masked -> display_value and carries a secret flag that the panel uses
to pick the input type, replacing the list it kept on its own side.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-23 22:10:36 +09:00
co-authored by Claude Opus 5
parent 2ced2e3cd5
commit cd38cbf19d
8 changed files with 42 additions and 14 deletions
+10 -2
View File
@@ -1,5 +1,6 @@
import asyncio
import logging
import os
import re
import httpx
@@ -10,7 +11,6 @@ from app.core import llm
from app.core.config import (
KNOWLEDGE_CONTEXT_LIMIT,
KNOWLEDGE_TOOL_CONTENT_LIMIT,
SEARCH_SUMMARY_MODEL,
)
from app.core.memory_kb import local_knowledge
from app.db.models import KnowledgeEntry, KnowledgeSource
@@ -37,6 +37,14 @@ _SUMMARY_PROMPT = (
_HEADLINE_MARKERS = ("要約:", "要約:")
def _summary_model() -> str | None:
"""GUIの設定画面から実行時に変更できるよう、起動時定数ではなく都度 os.environ を見に行く。
未設定(空文字含む)なら None を返し、llm.complete() 側で DEFAULT_MODEL にフォールバックさせる。
"""
return os.environ.get("SEARCH_SUMMARY_MODEL") or None
def _split_headline(text: str) -> tuple[str, str]:
"""LLMの出力を (一行要約, 本文) に分ける。1行目が想定の形式でなければ見出しは空で返す。"""
lines = text.strip().splitlines()
@@ -87,7 +95,7 @@ async def summarize_results(query: str, results: list[dict], model: str | None =
try:
text = await llm.complete(
[{"role": "user", "content": prompt}],
model=model or SEARCH_SUMMARY_MODEL,
model=model or _summary_model(),
)
except Exception:
logger.exception("Failed to summarize search results for query=%r", query)