feat: v1.2.0 - 三项优化

1. 模型选择改为两步式:先搜索选择基模型,再选择量化版本
   - 自动选中默认量化版本(Q4_K_M),后台可配置
   - 模型新增 base_model 字段,按基模型分组
   - 后台模型管理增加基模型字段

2. 参数搜索改为全局搜索
   - 搜索时跨所有分类显示匹配参数
   - 隐藏分类标签页,显示匹配数量

3. 自然语言支持 LLM 接口
   - 后台可配置 LLM API (URL/Key/Model/System Prompt)
   - 启用后优先调用 LLM 解析,失败自动回退正则解析
   - 兼容 OpenAI API 格式
This commit is contained in:
2026-07-19 22:57:38 +08:00
parent a115c5f7b4
commit 6691f37e45
7 changed files with 363 additions and 378 deletions
+76 -5
View File
@@ -7,6 +7,7 @@ import json
import re
import math
import functools
import urllib.request
from flask import Flask, request, jsonify, send_from_directory, session, redirect
from flask_cors import CORS
from db import get_db, init_db, DB_PATH
@@ -600,16 +601,86 @@ def get_models():
db.close()
return jsonify(result)
@app.route('/api/models/grouped')
def get_models_grouped():
db = get_db()
models = db.execute('SELECT * FROM models ORDER BY base_model, sort_order, name').fetchall()
db.close()
grouped = {}
for m in models:
d = dict(m)
base = d['base_model']
if base not in grouped:
grouped[base] = []
grouped[base].append(d)
# Get default quant from settings
db2 = get_db()
dq = db2.execute("SELECT value FROM settings WHERE key = 'default_quant'").fetchone()
db2.close()
default_quant = dq['value'] if dq else 'Q4_K_M'
return jsonify({'models': grouped, 'default_quant': default_quant})
# ----- Parse Natural Language -----
@app.route('/api/parse-nl', methods=['POST'])
def parse_nl():
data = request.json
text = data.get('text', '')
# Try LLM API first if enabled
db = get_db()
llm_enabled = db.execute("SELECT value FROM settings WHERE key = 'llm_enabled'").fetchone()
if llm_enabled and llm_enabled['value'] == 'true':
llm_url = db.execute("SELECT value FROM settings WHERE key = 'llm_api_url'").fetchone()
llm_key = db.execute("SELECT value FROM settings WHERE key = 'llm_api_key'").fetchone()
llm_model = db.execute("SELECT value FROM settings WHERE key = 'llm_api_model'").fetchone()
llm_prompt = db.execute("SELECT value FROM settings WHERE key = 'llm_system_prompt'").fetchone()
db.close()
url = llm_url['value'] if llm_url else ''
key = llm_key['value'] if llm_key else ''
model = llm_model['value'] if llm_model else ''
system_prompt = llm_prompt['value'] if llm_prompt else ''
if url:
try:
result = call_llm_for_parsing(url, key, model, system_prompt, text)
if result:
return jsonify(result)
except Exception as e:
print(f'LLM parse failed: {e}', file=sys.stderr)
else:
db.close()
# Fallback to regex parsing
result = parse_natural_language(text)
return jsonify(result)
def call_llm_for_parsing(url, key, model, system_prompt, user_text):
"""Call LLM API to parse natural language into params."""
headers = {'Content-Type': 'application/json'}
if key:
headers['Authorization'] = f'Bearer {key}'
body = {
'model': model,
'messages': [
{'role': 'system', 'content': system_prompt},
{'role': 'user', 'content': user_text}
],
'temperature': 0.1,
'max_tokens': 2000,
}
req = urllib.request.Request(url, data=json.dumps(body).encode('utf-8'), headers=headers, method='POST')
with urllib.request.urlopen(req, timeout=30) as resp:
data = json.loads(resp.read().decode('utf-8'))
# OpenAI-compatible response
content = data['choices'][0]['message']['content']
# Try to extract JSON from the response
content = content.strip()
if content.startswith('```'):
content = re.sub(r'^```\w*\n?', '', content)
content = re.sub(r'\n?```$', '', content)
result = json.loads(content)
return result
# ==================== Admin API ====================
# All admin routes below require login
@@ -800,9 +871,9 @@ def admin_add_model():
data = request.json
db = get_db()
db.execute(
'''INSERT INTO models (name, size_gb, layers, embd, kv_heads, head_dim, attention_heads, quant, description, sort_order)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',
(data['name'], data['size_gb'], data['layers'], data['embd'],
'''INSERT INTO models (base_model, name, size_gb, layers, embd, kv_heads, head_dim, attention_heads, quant, description, sort_order)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',
(data['base_model'], data['name'], data['size_gb'], data['layers'], data['embd'],
data['kv_heads'], data['head_dim'], data['attention_heads'],
data.get('quant', ''), data.get('description', ''), data.get('sort_order', 0))
)
@@ -818,9 +889,9 @@ def admin_model_edit(mid):
if request.method == 'PUT':
data = request.json
db.execute(
'''UPDATE models SET name=?, size_gb=?, layers=?, embd=?, kv_heads=?,
'''UPDATE models SET base_model=?, name=?, size_gb=?, layers=?, embd=?, kv_heads=?,
head_dim=?, attention_heads=?, quant=?, description=?, sort_order=? WHERE id=?''',
(data['name'], data['size_gb'], data['layers'], data['embd'],
(data['base_model'], data['name'], data['size_gb'], data['layers'], data['embd'],
data['kv_heads'], data['head_dim'], data['attention_heads'],
data.get('quant', ''), data.get('description', ''), data.get('sort_order', 0), mid)
)