aboutsummaryrefslogtreecommitdiffstats
path: root/test_llamachat.py
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-09 14:19:05 +0200
committerDanilo M. <danix@danix.xyz>2026-08-09 14:19:05 +0200
commit8e829a92c59aaaa8c6b14c3d52169ca0719209ab (patch)
tree7ca87cdfbaf8088b9a32fe7d30eb575c6318f663 /test_llamachat.py
parent67e1badee2e087bc673f252a5463c55e4ff4f9b1 (diff)
downloadllamachat-8e829a92c59aaaa8c6b14c3d52169ca0719209ab.tar.gz
llamachat-8e829a92c59aaaa8c6b14c3d52169ca0719209ab.zip
feat: namespace model ids by provider and filter model lists
Cloud models are addressed as provider:model; local ones stay bare so existing sessions keep resolving. An unknown prefix is treated as part of the model name rather than a provider. Filters are case-insensitive substrings because provider ids capitalise inconsistently. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'test_llamachat.py')
-rwxr-xr-xtest_llamachat.py67
1 files changed, 67 insertions, 0 deletions
diff --git a/test_llamachat.py b/test_llamachat.py
index 09d6203..5f6bad6 100755
--- a/test_llamachat.py
+++ b/test_llamachat.py
@@ -978,9 +978,75 @@ def test_provider_parsing():
"filter": "qwen"}}}
)
assert stringy["p"].filter == ["qwen"]
+
+ # Any other non-list shape is wrapped too, rather than iterated: a number
+ # would raise, and a dict would silently degrade into its keys.
+ odd = providers.parse(
+ {"providers": {"n": {"base_url": "http://x.example.org", "filter": 5},
+ "d": {"base_url": "http://y.example.org",
+ "filter": {"a": 1}}}}
+ )
+ assert odd["n"].filter == ["5"]
+ assert odd["d"].filter == ["{'a': 1}"]
print("ok provider config parsing")
+def test_model_ids_and_filtering():
+ """Ids are provider:model, local stays bare, filters are substrings."""
+ from llamachat import providers
+
+ table = providers.parse(
+ {
+ "providers": {
+ "local": {"base_url": "http://localhost:8181"},
+ "together": {
+ "base_url": "https://api.example.org",
+ "filter": ["qwen", "deepseek"],
+ },
+ "unfiltered": {"base_url": "https://api2.example.org"},
+ }
+ }
+ )
+
+ # Local models carry no prefix, in the dropdown and in the database.
+ assert providers.qualify("local", "gemma4") == "gemma4"
+ assert providers.qualify("together", "Qwen/Qwen2.5") == "together:Qwen/Qwen2.5"
+
+ # Splitting is the inverse, and only for providers that exist.
+ assert providers.split("gemma4", table) == ("local", "gemma4")
+ assert providers.split("together:Qwen/Qwen2.5", table) == (
+ "together",
+ "Qwen/Qwen2.5",
+ )
+ # An unknown prefix is part of the model name, not a provider. This is
+ # what keeps a local model whose name contains a colon working.
+ assert providers.split("weird:name", table) == ("local", "weird:name")
+ # Only the first colon splits.
+ assert providers.split("together:a:b", table) == ("together", "a:b")
+
+ # Filtering is case-insensitive substring, any match wins.
+ listed = [
+ "Qwen/Qwen2.5-72B-Instruct-Turbo",
+ "deepseek-ai/DeepSeek-V3",
+ "meta-llama/Llama-3.3-70B",
+ ]
+ kept = providers.apply_filter(table["together"], listed)
+ assert kept == [
+ "Qwen/Qwen2.5-72B-Instruct-Turbo",
+ "deepseek-ai/DeepSeek-V3",
+ ]
+
+ # No filter means everything.
+ assert providers.apply_filter(table["unfiltered"], listed) == listed
+ # The local provider is never filtered even if one is configured.
+ table["local"].filter = ["nothing-matches-this"]
+ assert providers.apply_filter(table["local"], listed) == listed
+ # A filter matching nothing yields nothing, it does not fall back to all.
+ table["together"].filter = ["zzz"]
+ assert providers.apply_filter(table["together"], listed) == []
+ print("ok model ids and filtering")
+
+
class _FakeResponse:
"""Enough of an http.client response for urlopen's context manager."""
@@ -1719,6 +1785,7 @@ if __name__ == "__main__":
test_venv_discovery()
test_config_defaults()
test_provider_parsing()
+ test_model_ids_and_filtering()
test_search_tool_schema()
test_search_results_sanitising()
test_tool_call_accumulation()