Reload Ollama models on URL change, pre-select current model
- /api/ollama-models accepts optional url query param to query a different endpoint - Frontend fetches models on load and on Ollama URL blur - Keeps current model selected if available, otherwise selects first in list - Shows loading indicator while fetching
This commit is contained in:
parent
f22bad6496
commit
94368670b7
@ -112,8 +112,12 @@ async def update_settings(
|
|||||||
return settings
|
return settings
|
||||||
|
|
||||||
@app.get("/api/ollama-models")
|
@app.get("/api/ollama-models")
|
||||||
async def get_ollama_models(db: Session = Depends(get_db), _ = Depends(require_admin_auth)):
|
async def get_ollama_models(
|
||||||
ollama_url = crud.get_setting(db, "ollama_url", "http://localhost:11434")
|
url: str = None,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
_ = Depends(require_admin_auth),
|
||||||
|
):
|
||||||
|
ollama_url = url or crud.get_setting(db, "ollama_url", "http://localhost:11434")
|
||||||
try:
|
try:
|
||||||
async with httpx.AsyncClient(timeout=5.0) as client:
|
async with httpx.AsyncClient(timeout=5.0) as client:
|
||||||
response = await client.get(f"{ollama_url}/api/tags")
|
response = await client.get(f"{ollama_url}/api/tags")
|
||||||
|
|||||||
@ -51,20 +51,40 @@ const EMPTY_KEY_FORM = {
|
|||||||
function SettingsSection({ password }) {
|
function SettingsSection({ password }) {
|
||||||
const [settings, setSettings] = useState(null);
|
const [settings, setSettings] = useState(null);
|
||||||
const [availableModels, setAvailableModels] = useState([]);
|
const [availableModels, setAvailableModels] = useState([]);
|
||||||
|
const [modelsLoading, setModelsLoading] = useState(false);
|
||||||
const [proxyEndpoint, setProxyEndpoint] = useState(null);
|
const [proxyEndpoint, setProxyEndpoint] = useState(null);
|
||||||
const [saved, setSaved] = useState(false);
|
const [saved, setSaved] = useState(false);
|
||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
|
|
||||||
|
const fetchModels = async (url, currentModel) => {
|
||||||
|
setModelsLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await axios.get('/api/ollama-models', {
|
||||||
|
headers: authHeaders(password),
|
||||||
|
params: url ? { url } : {},
|
||||||
|
});
|
||||||
|
const models = res.data.models;
|
||||||
|
setAvailableModels(models);
|
||||||
|
if (models.length > 0 && !models.includes(currentModel)) {
|
||||||
|
setSettings(s => ({ ...s, default_model: models[0] }));
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
setAvailableModels([]);
|
||||||
|
} finally {
|
||||||
|
setModelsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const headers = authHeaders(password);
|
const headers = authHeaders(password);
|
||||||
Promise.all([
|
Promise.all([
|
||||||
axios.get('/api/settings', { headers }),
|
axios.get('/api/settings', { headers }),
|
||||||
axios.get('/api/ollama-models', { headers }),
|
|
||||||
axios.get('/api/proxy-info', { headers }),
|
axios.get('/api/proxy-info', { headers }),
|
||||||
]).then(([settingsRes, modelsRes, proxyRes]) => {
|
]).then(([settingsRes, proxyRes]) => {
|
||||||
setSettings(settingsRes.data);
|
const s = settingsRes.data;
|
||||||
setAvailableModels(modelsRes.data.models);
|
setSettings(s);
|
||||||
setProxyEndpoint(proxyRes.data.endpoint);
|
setProxyEndpoint(proxyRes.data.endpoint);
|
||||||
|
fetchModels(s.ollama_url, s.default_model);
|
||||||
}).catch(() => setError('Einstellungen konnten nicht geladen werden.'));
|
}).catch(() => setError('Einstellungen konnten nicht geladen werden.'));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -100,13 +120,16 @@ function SettingsSection({ password }) {
|
|||||||
type="url"
|
type="url"
|
||||||
value={settings.ollama_url}
|
value={settings.ollama_url}
|
||||||
onChange={(e) => setSettings({ ...settings, ollama_url: e.target.value })}
|
onChange={(e) => setSettings({ ...settings, ollama_url: e.target.value })}
|
||||||
|
onBlur={(e) => fetchModels(e.target.value, settings.default_model)}
|
||||||
placeholder="http://localhost:11434"
|
placeholder="http://localhost:11434"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="settings-row">
|
<div className="settings-row">
|
||||||
<label>Standard-Modell</label>
|
<label>Standard-Modell</label>
|
||||||
{availableModels.length > 0 ? (
|
{modelsLoading ? (
|
||||||
|
<span className="settings-value">Lade Modelle…</span>
|
||||||
|
) : availableModels.length > 0 ? (
|
||||||
<select
|
<select
|
||||||
value={settings.default_model}
|
value={settings.default_model}
|
||||||
onChange={(e) => setSettings({ ...settings, default_model: e.target.value })}
|
onChange={(e) => setSettings({ ...settings, default_model: e.target.value })}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user