feat: 新增模型管理和供应商配置功能

### v1.1.0
- #### Added
  - 新增 AI 笔记风格选择
  - 新增 AI 笔记返回格式选择
  - 添加 AI 自定义笔记备注 Prompt
  - 添加任务失败重试
  - 添加全局设置页,可在设置页进行模型设置

- #### Optimize
  - 优化前端样式,优化用户体验
  - 增加生成中间产物,可用于失败后加快生成速度
- #### Fix
  - 修复视频截图视频过早删除错误
This commit is contained in:
思诺特
2025-04-26 23:40:17 +08:00
parent 1323cfd1ec
commit 171dea5e0d
51 changed files with 2511 additions and 414 deletions

View File

@@ -0,0 +1,42 @@
[
{
"id": "openai",
"name": "OpenAI",
"type": "built-in",
"logo": "OpenAI",
"api_key": "",
"base_url": "https://api.openai.com/v1"
},
{
"id": "deepseek",
"name": "DeepSeek",
"type": "built-in",
"logo": "DeepSeek",
"api_key": "",
"base_url": "https://api.deepseek.com"
},
{
"id": "qwen",
"name": "Qwen",
"type": "built-in",
"logo": "Qwen",
"api_key": "",
"base_url": "https://qwen.aliyun.com/api"
},
{
"id": "doubao",
"name": "豆包 (Doubao)",
"type": "built-in",
"logo": "Doubao",
"api_key": "",
"base_url": "https://open.doubao.com/api"
},
{
"id": "Claude",
"name": "Claude",
"type": "built-in",
"logo": "Claude",
"api_key": "",
"base_url": "https://"
}
]

View File

@@ -0,0 +1,58 @@
from app.db.sqlite_client import get_connection
def init_model_table():
conn = get_connection()
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS models (
id INTEGER PRIMARY KEY AUTOINCREMENT,
provider_id INTEGER NOT NULL,
model_name TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
conn.commit()
conn.close()
# 插入模型
def insert_model(provider_id: int, model_name: str):
conn = get_connection()
cursor = conn.cursor()
cursor.execute("""
INSERT INTO models (provider_id, model_name)
VALUES (?, ?)
""", (provider_id, model_name))
conn.commit()
conn.close()
# 根据provider查模型
def get_models_by_provider(provider_id: int):
conn = get_connection()
cursor = conn.cursor()
cursor.execute("""
SELECT id, model_name FROM models
WHERE provider_id = ?
""", (provider_id,))
rows = cursor.fetchall()
conn.close()
return [{"id": row[0], "model_name": row[1]} for row in rows]
# 删除某个模型
def delete_model(model_id: int):
conn = get_connection()
cursor = conn.cursor()
cursor.execute("""
DELETE FROM models WHERE id = ?
""", (model_id,))
conn.commit()
conn.close()
def get_all_models():
conn = get_connection()
cursor = conn.cursor()
cursor.execute("""
SELECT id, provider_id, model_name FROM models
""")
rows = cursor.fetchall()
conn.close()
return [{"id": row[0], "provider_id": row[1], "model_name": row[2]} for row in rows]

View File

@@ -1,8 +1,59 @@
import json
import os
from app.db.sqlite_client import get_connection
from app.utils.logger import get_logger
logger = get_logger(__name__)
def seed_default_providers():
conn = get_connection()
if conn is None:
logger.error("Failed to connect to database.")
return
cursor = conn.cursor()
# 检查已有数据
cursor.execute("SELECT COUNT(*) FROM providers")
count = cursor.fetchone()[0]
if count > 0:
logger.info("Providers already exist, skipping seed.")
conn.close()
return
json_path = os.path.join(os.path.dirname(__file__), 'builtin_providers.json')
try:
with open(json_path, 'r', encoding='utf-8') as f:
providers = json.load(f)
except Exception as e:
logger.error(f"Failed to read builtin_providers.json: {e}")
conn.close()
return
try:
for p in providers:
cursor.execute("""
INSERT INTO providers (id, name, api_key, base_url, logo, type, enabled)
VALUES (?, ?, ?, ?, ?, ?, ?)
""", (
p['id'],
p['name'],
p['api_key'],
p['base_url'],
p['logo'],
p['type'],
p.get('enabled', 1)
))
conn.commit()
logger.info("Default providers seeded successfully.")
except Exception as e:
logger.error(f"Failed to seed default providers: {e}")
finally:
conn.close()
def init_provider_table():
conn = get_connection()
if conn is None:
@@ -11,40 +62,60 @@ def init_provider_table():
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS providers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
logo TEXT NOT NULL,
type TEXT NOT NULL, -- ✅ 新增字段
type TEXT NOT NULL,
api_key TEXT NOT NULL,
base_url TEXT NOT NULL,
enabled INTEGER DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
try:
conn.commit()
conn.close()
logger.info("provider table created successfully.")
seed_default_providers()
except Exception as e:
logger.error(f"Failed to create provider table: {e}")
def insert_provider(name: str, api_key: str, base_url: str, logo: str, type_: str):
def insert_provider(id: str, name: str, api_key: str, base_url: str, logo: str, type_: str,enabled:int=1):
conn = get_connection()
if conn is None:
logger.error("Failed to connect to the database.")
return
cursor = conn.cursor()
cursor.execute("""
INSERT INTO providers (name, api_key, base_url, logo, type)
VALUES (?, ?, ?, ?, ?)
""", (name, api_key, base_url, logo, type_))
INSERT INTO providers (id, name, api_key, base_url, logo, type, enabled)
VALUES (?, ?, ?, ?, ?, ?, ?)
""", (id, name, api_key, base_url, logo, type_, enabled))
try:
conn.commit()
cursor_id = cursor.lastrowid
conn.close()
logger.info(f"Provider inserted successfully. name: {name}, type: {type_}")
return cursor_id
logger.info(f"Provider inserted successfully. id: {id}, name: {name}, type: {type_}")
return id
except Exception as e:
logger.error(f"Failed to insert provider: {e}")
return None
def get_enabled_providers():
conn = get_connection()
if conn is None:
logger.error("Failed to connect to the database.")
return
cursor = conn.cursor()
cursor.execute("SELECT * FROM providers WHERE enabled = 1")
try:
rows = cursor.fetchall()
conn.close()
if rows is None:
logger.info("No providers found")
return None
logger.info(f"Providers found: {rows}")
return rows
except Exception as e:
logger.error(f"Failed to get enabled providers: {e}")
def get_provider_by_name(name: str):
conn = get_connection()
if conn is None:
@@ -70,6 +141,7 @@ def get_provider_by_id(id: int):
return
cursor = conn.cursor()
cursor.execute("SELECT * FROM providers WHERE id = ?", (id,))
try:
row = cursor.fetchone()
conn.close()
@@ -99,23 +171,40 @@ def get_all_providers():
except Exception as e:
logger.error(f"Failed to get all providers: {e}")
def update_provider(id: int, name: str, api_key: str, base_url: str, logo: str, type_: str):
def update_provider(id: str, **kwargs):
conn = get_connection()
if conn is None:
logger.error("Failed to connect to the database.")
return
cursor = conn.cursor()
cursor.execute("""
UPDATE providers
SET name = ?, api_key = ?, base_url = ?, logo = ?, type = ?
fields = []
values = []
for key, value in kwargs.items():
fields.append(f"{key} = ?")
values.append(value)
if not fields:
logger.warning("No fields provided for update.")
return
sql = f"""
UPDATE providers
SET {', '.join(fields)}
WHERE id = ?
""", (name, api_key, base_url, logo, type_, id))
"""
values.append(id) # id 最后加
cursor = conn.cursor()
try:
cursor.execute(sql, values)
conn.commit()
conn.close()
logger.info(f"Provider updated successfully. id: {id}, type: {type_}")
logger.info(f"Provider updated successfully. id: {id}, updated_fields: {fields}")
except Exception as e:
logger.error(f"Failed to update provider: {e}")
def delete_provider(id: int):
conn = get_connection()
if conn is None: