feat: Update AI configuration items

This commit is contained in:
shiyu
2025-08-29 18:41:57 +08:00
parent cce39f7b1c
commit 81eed370a6
2 changed files with 46 additions and 25 deletions
+13 -7
View File
@@ -2,13 +2,14 @@ import httpx
from typing import List from typing import List
from services.config import ConfigCenter from services.config import ConfigCenter
async def describe_image_base64(base64_image: str, detail: str = "high") -> str: async def describe_image_base64(base64_image: str, detail: str = "high") -> str:
""" """
传入base64图片和文本提示,返回图片描述文本。 传入base64图片和文本提示,返回图片描述文本。
""" """
OAI_API_URL = await ConfigCenter.get("AI_API_URL", "https://api.siliconflow.cn/v1/chat/completions") OAI_API_URL = await ConfigCenter.get("AI_VISION_API_URL")
VISION_MODEL = await ConfigCenter.get("AI_VISION_MODEL", "Qwen/Qwen2.5-VL-32B-Instruct") VISION_MODEL = await ConfigCenter.get("AI_VISION_MODEL")
API_KEY = await ConfigCenter.get("AI_API_KEY", "") API_KEY = await ConfigCenter.get("AI_VISION_API_KEY")
payload = { payload = {
"model": VISION_MODEL, "model": VISION_MODEL,
"messages": [ "messages": [
@@ -42,13 +43,14 @@ async def describe_image_base64(base64_image: str, detail: str = "high") -> str:
except Exception as e: except Exception as e:
return f"请求失败: {str(e)}" return f"请求失败: {str(e)}"
async def get_text_embedding(text: str) -> List[float]: async def get_text_embedding(text: str) -> List[float]:
""" """
传入文本,返回嵌入向量。 传入文本,返回嵌入向量。
""" """
OAI_API_URL = await ConfigCenter.get("AI_API_URL", "https://api.siliconflow.cn/v1/chat/completions") OAI_API_URL = await ConfigCenter.get("AI_EMBED_API_URL")
EMBED_MODEL = await ConfigCenter.get("AI_EMBED_MODEL", "Qwen/Qwen3-Embedding-8B") EMBED_MODEL = await ConfigCenter.get("AI_EMBED_MODEL")
API_KEY = await ConfigCenter.get("AI_API_KEY", "") API_KEY = await ConfigCenter.get("AI_EMBED_API_KEY")
payload = { payload = {
"model": EMBED_MODEL, "model": EMBED_MODEL,
"input": text "input": text
@@ -58,7 +60,11 @@ async def get_text_embedding(text: str) -> List[float]:
"Content-Type": "application/json" "Content-Type": "application/json"
} }
async with httpx.AsyncClient() as client: async with httpx.AsyncClient() as client:
resp = await client.post(OAI_API_URL.replace("chat/completions", "embeddings"), headers=headers, json=payload) if OAI_API_URL.endswith("chat/completions"):
url = OAI_API_URL.replace("chat/completions", "embeddings")
else:
url = OAI_API_URL
resp = await client.post(url, headers=headers, json=payload)
resp.raise_for_status() resp.raise_for_status()
result = resp.json() result = resp.json()
return result["data"][0]["embedding"] return result["data"][0]["embedding"]
@@ -1,4 +1,4 @@
import { Form, Input, Button, message, Tabs, Space } from 'antd'; import { Form, Input, Button, message, Tabs, Space, Card } from 'antd';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import PageCard from '../../components/PageCard'; import PageCard from '../../components/PageCard';
import { getAllConfig, setConfig } from '../../api/config'; import { getAllConfig, setConfig } from '../../api/config';
@@ -11,13 +11,20 @@ const APP_CONFIG_KEYS = [
{ key: 'SERVER_URL', label: '服务端URL', default: API_BASE_URL }, { key: 'SERVER_URL', label: '服务端URL', default: API_BASE_URL },
]; ];
const AI_CONFIG_KEYS = [ const VISION_CONFIG_KEYS = [
{ key: 'AI_API_URL', label: 'AI API地址' }, { key: 'AI_VISION_API_URL', label: '视觉模型 API 地址' },
{ key: 'AI_VISION_MODEL', label: '视觉模型' }, { key: 'AI_VISION_MODEL', label: '视觉模型', default: 'Qwen/Qwen2.5-VL-32B-Instruct' },
{ key: 'AI_EMBED_MODEL', label: '嵌入模型' }, { key: 'AI_VISION_API_KEY', label: '视觉模型 API Key' },
{ key: 'AI_API_KEY', label: 'API Key' },
]; ];
const EMBED_CONFIG_KEYS = [
{ key: 'AI_EMBED_API_URL', label: '嵌入模型 API 地址' },
{ key: 'AI_EMBED_MODEL', label: '嵌入模型', default: 'Qwen/Qwen3-Embedding-8B' },
{ key: 'AI_EMBED_API_KEY', label: '嵌入模型 API Key' },
];
const ALL_AI_KEYS = [...VISION_CONFIG_KEYS, ...EMBED_CONFIG_KEYS];
export default function SystemSettingsPage() { export default function SystemSettingsPage() {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [config, setConfigState] = useState<Record<string, string> | null>(null); const [config, setConfigState] = useState<Record<string, string> | null>(null);
@@ -41,14 +48,13 @@ export default function SystemSettingsPage() {
setLoading(false); setLoading(false);
}; };
// 加载中时不渲染表单
if (!config) { if (!config) {
return <PageCard title='系统设置'><div>...</div></PageCard>; return <PageCard title='系统设置'><div>...</div></PageCard>;
} }
return ( return (
<PageCard <PageCard
title='系统设置' title='系统设置'
> >
<Space direction="vertical" style={{ width: '100%' }} size={32}> <Space direction="vertical" style={{ width: '100%' }} size={32}>
<Tabs <Tabs
@@ -100,18 +106,27 @@ export default function SystemSettingsPage() {
<Form <Form
layout="vertical" layout="vertical"
initialValues={{ initialValues={{
...Object.fromEntries(AI_CONFIG_KEYS.map(({ key }) => [key, config[key] ?? ''])), ...Object.fromEntries(ALL_AI_KEYS.map(({ key, default: def }) => [key, config[key] ?? def ?? ''])),
}} }}
onFinish={handleSave} onFinish={handleSave}
style={{ marginTop: 24 }} style={{ marginTop: 24 }}
key={JSON.stringify(config)} // 强制表单重置 key={JSON.stringify(config)}
> >
{AI_CONFIG_KEYS.map(({ key, label }) => ( <Card title="视觉模型" style={{ marginBottom: 24 }}>
<Form.Item key={key} name={key} label={label}> {VISION_CONFIG_KEYS.map(({ key, label }) => (
<Input size="large" /> <Form.Item key={key} name={key} label={label}>
</Form.Item> <Input size="large" />
))} </Form.Item>
<Form.Item> ))}
</Card>
<Card title="嵌入模型">
{EMBED_CONFIG_KEYS.map(({ key, label }) => (
<Form.Item key={key} name={key} label={label}>
<Input size="large" />
</Form.Item>
))}
</Card>
<Form.Item style={{ marginTop: 24 }}>
<Button type="primary" htmlType="submit" loading={loading} block> <Button type="primary" htmlType="submit" loading={loading} block>
</Button> </Button>