diff options
Diffstat (limited to 'llamachat/config.py')
| -rw-r--r-- | llamachat/config.py | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/llamachat/config.py b/llamachat/config.py index dec2ba6..d7682f0 100644 --- a/llamachat/config.py +++ b/llamachat/config.py @@ -37,6 +37,14 @@ DEFAULTS = { # Named prompt selected for new conversations. Empty means the global # default.md, and "none" means no system prompt at all. "default_prompt": "", + # Web search through a SearXNG instance. Off unless both the flag is set + # and a URL is given, so an upgrade never starts talking to the network. + "search_enabled": False, + "search_url": "", + "search_results": 5, + "search_snippet_chars": 300, + "search_timeout": 10, + "max_searches": 2, } # The global prompt lives here; every other .md beside it is a named preset. @@ -67,6 +75,12 @@ class Config: default_prompt: str prompts_dir: Path state_path: Path + search_enabled: bool + search_url: str + search_results: int + search_snippet_chars: int + search_timeout: int + max_searches: int def _runtime_dir() -> Path: @@ -94,6 +108,11 @@ def load(path: Path = CONFIG_PATH) -> Config: socket = values["socket"] or (_runtime_dir() / "llamachat.sock") db = values["db"] or (_data_dir() / "history.db") + # A flag with no URL behind it is not enabled, it is misconfigured. + # Resolving that here means nothing downstream has to test both. + search_url = str(values["search_url"]).rstrip("/") + search_enabled = bool(values["search_enabled"]) and bool(search_url) + return Config( base_url=str(values["base_url"]).rstrip("/"), presets_path=Path(values["presets"]).expanduser(), @@ -108,6 +127,12 @@ def load(path: Path = CONFIG_PATH) -> Config: # Window layout, remembered between runs. Not user-editable config, # so it sits beside it rather than inside config.toml. state_path=path.parent / "state.ini", + search_enabled=search_enabled, + search_url=search_url, + search_results=int(values["search_results"]), + search_snippet_chars=int(values["search_snippet_chars"]), + search_timeout=int(values["search_timeout"]), + max_searches=int(values["max_searches"]), ) @@ -143,6 +168,27 @@ def write_default(path: Path = CONFIG_PATH) -> Path: '# chars-per-token estimate used to convert ctx-size into characters.\n' f'attach_ctx_fraction = {DEFAULTS["attach_ctx_fraction"]}\n' f'chars_per_token = {DEFAULTS["chars_per_token"]}\n' + '\n' + '# Web search through SearXNG. The model decides when to search; it\n' + '# is offered a web_search tool and calls it when a question needs\n' + '# current information. Both search_enabled and search_url are\n' + '# required: a flag with no URL stays off.\n' + '#\n' + '# The instance must have its JSON API enabled (format=json), which\n' + '# many installs turn off by default.\n' + '#\n' + '# Search results are untrusted text entering the model context.\n' + '# Only title, url and snippet are kept, snippets are truncated, and\n' + '# result links are shown but never fetched automatically.\n' + f'search_enabled = {str(DEFAULTS["search_enabled"]).lower()}\n' + f'search_url = "{DEFAULTS["search_url"]}"\n' + '\n' + '# Results per query, characters kept from each snippet, seconds\n' + '# before a query is abandoned, and searches allowed per turn.\n' + f'search_results = {DEFAULTS["search_results"]}\n' + f'search_snippet_chars = {DEFAULTS["search_snippet_chars"]}\n' + f'search_timeout = {DEFAULTS["search_timeout"]}\n' + f'max_searches = {DEFAULTS["max_searches"]}\n' ) return path |
