v1.1.0 新增大模型配置管理:页面可配置分析网页的LLM接口(名称/BaseURL/Key/模型/温度/超时/默认),支持视觉标记——视觉模型走截图视觉分析路线,非视觉模型走DOM快照文本分析路线;任务创建可选模型并记录使用情况
This commit is contained in:
@@ -34,17 +34,51 @@ def init_db():
|
||||
report_path TEXT
|
||||
)
|
||||
''')
|
||||
# 大模型配置表
|
||||
c.execute('''
|
||||
CREATE TABLE IF NOT EXISTS llm_configs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
base_url TEXT NOT NULL,
|
||||
api_key TEXT NOT NULL,
|
||||
model TEXT NOT NULL,
|
||||
vision INTEGER DEFAULT 0,
|
||||
temperature REAL DEFAULT 0.2,
|
||||
timeout INTEGER DEFAULT 120,
|
||||
is_default INTEGER DEFAULT 0,
|
||||
created_at REAL
|
||||
)
|
||||
''')
|
||||
# tasks 表迁移:新增模型相关列(老库升级)
|
||||
cols = [r[1] for r in c.execute('PRAGMA table_info(tasks)')]
|
||||
if 'llm_config_id' not in cols:
|
||||
c.execute('ALTER TABLE tasks ADD COLUMN llm_config_id INTEGER')
|
||||
if 'llm_name' not in cols:
|
||||
c.execute('ALTER TABLE tasks ADD COLUMN llm_name TEXT')
|
||||
if 'vision' not in cols:
|
||||
c.execute('ALTER TABLE tasks ADD COLUMN vision INTEGER DEFAULT 0')
|
||||
# 首次启动:写入默认模型配置
|
||||
n = c.execute('SELECT COUNT(*) FROM llm_configs').fetchone()[0]
|
||||
if n == 0:
|
||||
from config import (LLM_BASE_URL, LLM_API_KEY, LLM_MODEL,
|
||||
LLM_TEMPERATURE, LLM_TIMEOUT, DEFAULT_LLM_NAME)
|
||||
c.execute(
|
||||
'INSERT INTO llm_configs (name, base_url, api_key, model, vision, '
|
||||
'temperature, timeout, is_default, created_at) VALUES (?,?,?,?,?,?,?,?,?)',
|
||||
(DEFAULT_LLM_NAME, LLM_BASE_URL, LLM_API_KEY, LLM_MODEL, 0,
|
||||
LLM_TEMPERATURE, LLM_TIMEOUT, 1, time.time()))
|
||||
c.commit()
|
||||
c.close()
|
||||
|
||||
|
||||
def create_task(url, goal, max_steps, timeout):
|
||||
def create_task(url, goal, max_steps, timeout, llm_config_id=None, llm_name=None, vision=0):
|
||||
tid = uuid.uuid4().hex[:12]
|
||||
c = _conn()
|
||||
c.execute(
|
||||
'INSERT INTO tasks (id, url, goal, status, max_steps, timeout, created_at) '
|
||||
'VALUES (?,?,?,?,?,?,?)',
|
||||
(tid, url, goal, 'queued', max_steps, timeout, time.time()))
|
||||
'INSERT INTO tasks (id, url, goal, status, max_steps, timeout, created_at, '
|
||||
'llm_config_id, llm_name, vision) VALUES (?,?,?,?,?,?,?,?,?,?)',
|
||||
(tid, url, goal, 'queued', max_steps, timeout, time.time(),
|
||||
llm_config_id, llm_name, 1 if vision else 0))
|
||||
c.commit()
|
||||
c.close()
|
||||
return tid
|
||||
@@ -104,3 +138,97 @@ def load_step_logs(tid):
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
return out
|
||||
|
||||
|
||||
# ========== 大模型配置 ==========
|
||||
|
||||
|
||||
def list_llm_configs():
|
||||
c = _conn()
|
||||
rows = c.execute(
|
||||
'SELECT * FROM llm_configs ORDER BY is_default DESC, id ASC'
|
||||
).fetchall()
|
||||
c.close()
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
|
||||
def get_llm_config(cid):
|
||||
c = _conn()
|
||||
row = c.execute('SELECT * FROM llm_configs WHERE id=?', (cid,)).fetchone()
|
||||
c.close()
|
||||
return dict(row) if row else None
|
||||
|
||||
|
||||
def get_default_llm_config():
|
||||
c = _conn()
|
||||
row = c.execute('SELECT * FROM llm_configs WHERE is_default=1').fetchone()
|
||||
if not row:
|
||||
row = c.execute('SELECT * FROM llm_configs ORDER BY id ASC').fetchone()
|
||||
c.close()
|
||||
return dict(row) if row else None
|
||||
|
||||
|
||||
def create_llm_config(name, base_url, api_key, model, vision=0,
|
||||
temperature=0.2, timeout=120, is_default=False):
|
||||
c = _conn()
|
||||
if is_default:
|
||||
c.execute('UPDATE llm_configs SET is_default=0')
|
||||
c.execute(
|
||||
'INSERT INTO llm_configs (name, base_url, api_key, model, vision, '
|
||||
'temperature, timeout, is_default, created_at) VALUES (?,?,?,?,?,?,?,?,?)',
|
||||
(name, base_url, api_key, model, 1 if vision else 0,
|
||||
temperature, timeout, 1 if is_default else 0, time.time()))
|
||||
c.commit()
|
||||
cid = c.execute('SELECT last_insert_rowid()').fetchone()[0]
|
||||
c.close()
|
||||
return cid
|
||||
|
||||
|
||||
def update_llm_config(cid, **fields):
|
||||
allowed = {'name', 'base_url', 'api_key', 'model', 'vision',
|
||||
'temperature', 'timeout', 'is_default'}
|
||||
c = _conn()
|
||||
if fields.get('is_default'):
|
||||
c.execute('UPDATE llm_configs SET is_default=0')
|
||||
sets = []
|
||||
vals = []
|
||||
for k, v in fields.items():
|
||||
if k not in allowed:
|
||||
continue
|
||||
if k == 'vision':
|
||||
v = 1 if v else 0
|
||||
if k == 'is_default':
|
||||
v = 1 if v else 0
|
||||
sets.append(f'{k}=?')
|
||||
vals.append(v)
|
||||
if sets:
|
||||
c.execute(f'UPDATE llm_configs SET {", ".join(sets)} WHERE id=?', (*vals, cid))
|
||||
c.commit()
|
||||
c.close()
|
||||
|
||||
|
||||
def delete_llm_config(cid):
|
||||
c = _conn()
|
||||
c.execute('DELETE FROM llm_configs WHERE id=?', (cid,))
|
||||
c.commit()
|
||||
c.close()
|
||||
|
||||
|
||||
def set_default_llm_config(cid):
|
||||
c = _conn()
|
||||
c.execute('UPDATE llm_configs SET is_default=0')
|
||||
c.execute('UPDATE llm_configs SET is_default=1 WHERE id=?', (cid,))
|
||||
c.commit()
|
||||
c.close()
|
||||
|
||||
|
||||
def llm_config_to_dict(row):
|
||||
"""把配置行转成 llm.py 可用的 dict(不含数据库元信息)"""
|
||||
return {
|
||||
'base_url': row['base_url'],
|
||||
'api_key': row['api_key'],
|
||||
'model': row['model'],
|
||||
'temperature': row['temperature'],
|
||||
'timeout': row['timeout'],
|
||||
'vision': bool(row['vision']),
|
||||
}
|
||||
Reference in New Issue
Block a user