Add custom API URL and model to AI settings
- Settings → AI: optional base URL and model name fields - Defaults to Anthropic/OpenAI public APIs when left blank - Custom URL enables Open WebUI, LM Studio, Ollama, and any OpenAI-compatible endpoint - Parse endpoint uses custom base URL and model if configured - Migration 0004: ai_base_url + ai_model columns on users - OpenAI provider label updated to "OpenAI-compatible" Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b1c160f607
commit
d6118bac54
6 changed files with 124 additions and 29 deletions
|
|
@ -20,11 +20,15 @@ SUPPORTED_PROVIDERS = {"anthropic", "openai"}
|
|||
class AiSettingsResponse(BaseModel):
|
||||
provider: str | None
|
||||
has_api_key: bool
|
||||
base_url: str | None
|
||||
model: str | None
|
||||
|
||||
|
||||
class AiSettingsSave(BaseModel):
|
||||
provider: str
|
||||
api_key: str
|
||||
api_key: str = ""
|
||||
base_url: str = ""
|
||||
model: str = ""
|
||||
|
||||
|
||||
@router.get("/ai", response_model=AiSettingsResponse)
|
||||
|
|
@ -32,6 +36,8 @@ async def get_ai_settings(user: User = Depends(get_current_user)):
|
|||
return AiSettingsResponse(
|
||||
provider=user.ai_provider,
|
||||
has_api_key=bool(user.ai_api_key_enc),
|
||||
base_url=user.ai_base_url,
|
||||
model=user.ai_model,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -43,17 +49,26 @@ async def save_ai_settings(
|
|||
):
|
||||
if body.provider not in SUPPORTED_PROVIDERS:
|
||||
raise HTTPException(status_code=400, detail=f"Unsupported provider. Choose: {', '.join(SUPPORTED_PROVIDERS)}")
|
||||
if not body.api_key.strip():
|
||||
raise HTTPException(status_code=400, detail="api_key must not be empty")
|
||||
|
||||
encrypted = encrypt_field(body.api_key.strip())
|
||||
await db.execute(
|
||||
update(User)
|
||||
.where(User.id == user.id)
|
||||
.values(ai_provider=body.provider, ai_api_key_enc=encrypted)
|
||||
)
|
||||
values: dict = {
|
||||
"ai_provider": body.provider,
|
||||
"ai_base_url": body.base_url.rstrip("/") or None,
|
||||
"ai_model": body.model.strip() or None,
|
||||
}
|
||||
|
||||
if body.api_key.strip():
|
||||
values["ai_api_key_enc"] = encrypt_field(body.api_key.strip())
|
||||
elif not user.ai_api_key_enc:
|
||||
raise HTTPException(status_code=400, detail="api_key is required when no key is saved yet")
|
||||
|
||||
await db.execute(update(User).where(User.id == user.id).values(**values))
|
||||
await db.commit()
|
||||
return AiSettingsResponse(provider=body.provider, has_api_key=True)
|
||||
return AiSettingsResponse(
|
||||
provider=body.provider,
|
||||
has_api_key=True,
|
||||
base_url=values["ai_base_url"],
|
||||
model=values["ai_model"],
|
||||
)
|
||||
|
||||
|
||||
@router.delete("/ai", status_code=204)
|
||||
|
|
@ -64,6 +79,6 @@ async def clear_ai_settings(
|
|||
await db.execute(
|
||||
update(User)
|
||||
.where(User.id == user.id)
|
||||
.values(ai_provider=None, ai_api_key_enc=None)
|
||||
.values(ai_provider=None, ai_api_key_enc=None, ai_base_url=None, ai_model=None)
|
||||
)
|
||||
await db.commit()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue