mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-09-07 08:36:49 +08:00
feat: Update AI configuration items
This commit is contained in:
+13
-7
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user