64 lines
4.1 KiB
Python
64 lines
4.1 KiB
Python
from pathlib import Path
|
|
import shutil
|
|
|
|
root = Path(r'C:\kefu\wechat_rpa')
|
|
artifacts = Path(__file__).resolve().parent
|
|
for name in ('admin_backend.py', 'admin_api.py'):
|
|
if not (artifacts / (name + '.before')).exists():
|
|
shutil.copy2(root / name, artifacts / (name + '.before'))
|
|
|
|
path = root / 'admin_backend.py'
|
|
text = path.read_text(encoding='utf-8')
|
|
text = text.replace('from datetime import datetime, timedelta', 'from datetime import datetime, timedelta, timezone')
|
|
schema = ''' CREATE TABLE IF NOT EXISTS model_usage_events (
|
|
event_id TEXT PRIMARY KEY NOT NULL,
|
|
request_id TEXT NOT NULL DEFAULT '',
|
|
task_id TEXT NOT NULL DEFAULT '',
|
|
tenant_id TEXT NOT NULL DEFAULT '',
|
|
desktop_account_id INTEGER,
|
|
provider_id TEXT NOT NULL DEFAULT '',
|
|
provider_name TEXT NOT NULL DEFAULT '',
|
|
model TEXT NOT NULL DEFAULT '',
|
|
kind TEXT NOT NULL DEFAULT '',
|
|
purpose TEXT NOT NULL CHECK(purpose IN ('chat','guard','knowledge')),
|
|
role TEXT NOT NULL CHECK(role IN ('answer','judge')),
|
|
attempt INTEGER NOT NULL CHECK(attempt >= 1),
|
|
status TEXT NOT NULL CHECK(status IN ('success','error')),
|
|
input_tokens INTEGER CHECK(input_tokens IS NULL OR input_tokens >= 0),
|
|
output_tokens INTEGER CHECK(output_tokens IS NULL OR output_tokens >= 0),
|
|
total_tokens INTEGER CHECK(total_tokens IS NULL OR total_tokens >= 0),
|
|
cached_input_tokens INTEGER CHECK(cached_input_tokens IS NULL OR cached_input_tokens >= 0),
|
|
reasoning_tokens INTEGER CHECK(reasoning_tokens IS NULL OR reasoning_tokens >= 0),
|
|
latency_ms INTEGER NOT NULL CHECK(latency_ms >= 0),
|
|
created_at TEXT NOT NULL
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_model_usage_created
|
|
ON model_usage_events(created_at DESC, event_id);
|
|
CREATE INDEX IF NOT EXISTS idx_model_usage_tenant_created
|
|
ON model_usage_events(tenant_id, created_at DESC, event_id);
|
|
CREATE INDEX IF NOT EXISTS idx_model_usage_provider_created
|
|
ON model_usage_events(provider_id, model, created_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_model_usage_purpose_created
|
|
ON model_usage_events(purpose, created_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_model_usage_tenant_task
|
|
ON model_usage_events(tenant_id, task_id) WHERE task_id != '';
|
|
'''
|
|
marker = ' CREATE INDEX IF NOT EXISTS idx_tokens_digest ON auth_tokens(token_digest);'
|
|
assert marker in text and 'CREATE TABLE IF NOT EXISTS model_usage_events' not in text
|
|
text = text.replace(marker, schema + marker, 1)
|
|
methods = artifacts.joinpath('usage_methods.txt').read_text(encoding='utf-8')
|
|
marker = ' # ── 角色与权限 ────────────────────────────────────────────────────────'
|
|
assert marker in text and 'def record_model_usage(' not in text
|
|
text = text.replace(marker, methods + '\n' + marker, 1)
|
|
path.write_text(text, encoding='utf-8', newline='')
|
|
|
|
path = root / 'admin_api.py'
|
|
text = path.read_text(encoding='utf-8')
|
|
text = text.replace('from fastapi import Depends, FastAPI, HTTPException, Request, status', 'from fastapi import Depends, FastAPI, HTTPException, Query, Request, status')
|
|
routes = artifacts.joinpath('usage_routes.txt').read_text(encoding='utf-8')
|
|
marker = ' # ── 桌面端配置 ───────────────────────────────────────────────────────'
|
|
assert marker in text and '/api/v2/stats/model-usage' not in text
|
|
text = text.replace(marker, routes + '\n' + marker, 1)
|
|
path.write_text(text, encoding='utf-8', newline='')
|
|
print('usage schema, database API and HTTP routes patched')
|