Skip to content

Commit e379031

Browse files
authored
Include api_base in config parameters REST API (#22)
* include api_base in config parameters * exercise put model-params and fix config manager key
1 parent c4dd8b2 commit e379031

File tree

3 files changed

+63
-6
lines changed

3 files changed

+63
-6
lines changed

jupyter_ai_jupyternaut/models/parameter_schemas.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
},
108108
"api_base": {
109109
"type": "string",
110-
"description": "Base URL where LLM requests are sent, used for enterprise proxy gateways."
110+
"description": "Base URL where LLM requests are sent, used for local models, enterprise proxies, or other hosting providers (e.g. vLLM)."
111111
}
112112
}
113113

jupyter_ai_jupyternaut/models/parameters_rest_api.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ def get(self):
3232

3333
# Temporary common parameters that work across most models
3434
common_params = ["temperature", "max_tokens", "top_p", "stop"]
35+
# parameters that are actually inputs to the client, not the model
36+
# always include these (get_supported_openai_params doesn't include them)
37+
client_params = ["api_base"]
3538
# Params controlling tool availability & usage require a unique UX
3639
# if they are to be made configurable from the frontend. Therefore
3740
# they are disabled for now.
@@ -49,7 +52,8 @@ def get(self):
4952
parameter_names = common_params
5053
else:
5154
parameter_names = common_params
52-
55+
# always include client parameters
56+
parameter_names.extend(client_params)
5357
# Filter out excluded params
5458
parameter_names = [n for n in parameter_names if n not in EXCLUDED_PARAMS]
5559

@@ -109,7 +113,7 @@ def put(self):
109113
except ValueError as e:
110114
raise HTTPError(400, f"Invalid value for parameter '{param_name}': {str(e)}")
111115

112-
config_manager = self.settings.get("jai_config_manager")
116+
config_manager = self.settings.get("jupyternaut.config_manager")
113117
if not config_manager:
114118
raise HTTPError(500, "Config manager not available")
115119

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import json
2+
import pytest
3+
4+
from jupyter_ai_jupyternaut.models import parameter_schemas
25

36

47
async def test_get_example(jp_fetch):
@@ -8,6 +11,56 @@ async def test_get_example(jp_fetch):
811
# Then
912
assert response.code == 200
1013
payload = json.loads(response.body)
11-
assert payload == {
12-
"data": "This is /api/jupyternaut/get-example endpoint!"
13-
}
14+
assert payload == {"data": "This is /api/jupyternaut/get-example endpoint!"}
15+
16+
17+
@pytest.mark.parametrize(
18+
"model",
19+
[
20+
None,
21+
"openai/gpt-oss-120b",
22+
"hosted_vllm/doesntmatter",
23+
"anthropic/claude-3-5-haiku-latest",
24+
],
25+
)
26+
async def test_get_parameters(jp_fetch, model):
27+
params = {}
28+
if model:
29+
params["model"] = model
30+
response = await jp_fetch("api/jupyternaut/model-parameters", params=params)
31+
assert response.code == 200
32+
payload = json.loads(response.body)
33+
expected_params = [
34+
"api_base",
35+
"max_tokens",
36+
"stop",
37+
"temperature",
38+
"top_p",
39+
]
40+
if model:
41+
expected_params.extend(["max_completion_tokens"])
42+
if not model.startswith("anthropic/"):
43+
expected_params.extend(["frequency_penalty"])
44+
45+
for param in expected_params:
46+
assert param in payload["parameter_names"]
47+
assert param in payload["parameters"]
48+
assert "description" in payload["parameters"][param]
49+
50+
51+
async def test_put_params(jp_fetch):
52+
# TODO: validate all types, error handling
53+
response = await jp_fetch(
54+
"api/jupyternaut/model-parameters",
55+
body=json.dumps({
56+
"model_id": "hosted_vllm/mlx-community/gpt-oss-20b-MXFP4-Q8",
57+
"parameters": {
58+
"api_base": {
59+
"value": "http://127.0.0.1:8080",
60+
"type": "string",
61+
},
62+
},
63+
}),
64+
method="PUT",
65+
)
66+
assert response.code == 200

0 commit comments

Comments
 (0)