feat: add OpenClaw LLM scoring pipeline for all domains and surface in panel
This commit is contained in:
parent
75300a1005
commit
df0f0515a0
5
api.php
5
api.php
@ -33,12 +33,15 @@ if ($action === 'domains') {
|
|||||||
$prevRunId = $prev['run_id'] ?? '';
|
$prevRunId = $prev['run_id'] ?? '';
|
||||||
|
|
||||||
$sql = "SELECT d.domain, d.tld, d.score, d.status, d.keywords_json,
|
$sql = "SELECT d.domain, d.tld, d.score, d.status, d.keywords_json,
|
||||||
|
ls.llm_score, ls.decision, ls.reason,
|
||||||
CASE
|
CASE
|
||||||
WHEN :prev = '' THEN 1
|
WHEN :prev = '' THEN 1
|
||||||
WHEN EXISTS (SELECT 1 FROM domains p WHERE p.run_id = :prev AND p.domain = d.domain) THEN 0
|
WHEN EXISTS (SELECT 1 FROM domains p WHERE p.run_id = :prev AND p.domain = d.domain) THEN 0
|
||||||
ELSE 1
|
ELSE 1
|
||||||
END AS is_new
|
END AS is_new
|
||||||
FROM domains d WHERE d.run_id = :run";
|
FROM domains d
|
||||||
|
LEFT JOIN llm_scores ls ON ls.run_id = d.run_id AND ls.domain = d.domain
|
||||||
|
WHERE d.run_id = :run";
|
||||||
|
|
||||||
if ($q !== '') $sql .= " AND d.domain LIKE :q";
|
if ($q !== '') $sql .= " AND d.domain LIKE :q";
|
||||||
if ($tld !== '') $sql .= " AND d.tld = :tld";
|
if ($tld !== '') $sql .= " AND d.tld = :tld";
|
||||||
|
|||||||
23
export_latest_domains.py
Executable file
23
export_latest_domains.py
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import json
|
||||||
|
import sqlite3
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
BASE = Path(__file__).resolve().parent
|
||||||
|
DB = BASE / 'data' / 'domainhunter.db'
|
||||||
|
|
||||||
|
con = sqlite3.connect(DB)
|
||||||
|
cur = con.cursor()
|
||||||
|
run_id = cur.execute("SELECT value FROM metadata WHERE key='latest_run_id'").fetchone()
|
||||||
|
run_id = run_id[0] if run_id else ''
|
||||||
|
scanned = cur.execute("SELECT value FROM metadata WHERE key='latest_scanned_at'").fetchone()
|
||||||
|
scanned = scanned[0] if scanned else ''
|
||||||
|
rows = cur.execute("SELECT domain,tld,score,status,keywords_json FROM domains WHERE run_id=? ORDER BY score DESC,domain ASC", (run_id,)).fetchall()
|
||||||
|
items=[]
|
||||||
|
for d,tld,score,status,kw in rows:
|
||||||
|
try:
|
||||||
|
kws=json.loads(kw or '[]')
|
||||||
|
except Exception:
|
||||||
|
kws=[]
|
||||||
|
items.append({"domain":d,"tld":tld,"score":score,"status":status,"keywords":kws})
|
||||||
|
print(json.dumps({"runId":run_id,"scannedAt":scanned,"items":items}, ensure_ascii=False, indent=2))
|
||||||
71
import_llm_scores.py
Executable file
71
import_llm_scores.py
Executable file
@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import json
|
||||||
|
import sqlite3
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
BASE = Path(__file__).resolve().parent
|
||||||
|
DB = BASE / 'data' / 'domainhunter.db'
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print('Usage: import_llm_scores.py <json-file>')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
src = Path(sys.argv[1])
|
||||||
|
if not src.exists():
|
||||||
|
print(f'File not found: {src}')
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
payload = json.loads(src.read_text(encoding='utf-8'))
|
||||||
|
items = payload if isinstance(payload, list) else payload.get('items', [])
|
||||||
|
|
||||||
|
con = sqlite3.connect(DB)
|
||||||
|
cur = con.cursor()
|
||||||
|
cur.executescript('''
|
||||||
|
CREATE TABLE IF NOT EXISTS llm_scores (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
run_id TEXT,
|
||||||
|
domain TEXT,
|
||||||
|
llm_score REAL,
|
||||||
|
decision TEXT,
|
||||||
|
reason TEXT,
|
||||||
|
updated_at TEXT,
|
||||||
|
UNIQUE(run_id, domain)
|
||||||
|
);
|
||||||
|
''')
|
||||||
|
|
||||||
|
run_id = None
|
||||||
|
if isinstance(payload, dict):
|
||||||
|
run_id = payload.get('runId')
|
||||||
|
if not run_id:
|
||||||
|
r = cur.execute("SELECT value FROM metadata WHERE key='latest_run_id'").fetchone()
|
||||||
|
run_id = (r[0] if r else '')
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
for it in items:
|
||||||
|
d = (it.get('domain') or '').strip().lower()
|
||||||
|
if not d:
|
||||||
|
continue
|
||||||
|
score = it.get('llm_score', None)
|
||||||
|
dec = (it.get('decision') or '').strip().lower()[:32]
|
||||||
|
reason = (it.get('reason') or '').strip()[:500]
|
||||||
|
cur.execute('''
|
||||||
|
INSERT INTO llm_scores(run_id, domain, llm_score, decision, reason, updated_at)
|
||||||
|
VALUES(?,?,?,?,?,datetime('now'))
|
||||||
|
ON CONFLICT(run_id, domain) DO UPDATE SET
|
||||||
|
llm_score=excluded.llm_score,
|
||||||
|
decision=excluded.decision,
|
||||||
|
reason=excluded.reason,
|
||||||
|
updated_at=excluded.updated_at
|
||||||
|
''', (run_id, d, score, dec, reason))
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
con.commit()
|
||||||
|
con.close()
|
||||||
|
print(f'OK imported llm scores: {count} for run {run_id}')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@ -54,7 +54,7 @@
|
|||||||
<h2>TOP domen + porównanie cen (rejestracja / odnowienie)</h2>
|
<h2>TOP domen + porównanie cen (rejestracja / odnowienie)</h2>
|
||||||
<div class="table-wrap">
|
<div class="table-wrap">
|
||||||
<table>
|
<table>
|
||||||
<thead><tr><th>Domena</th><th>TLD</th><th>Score</th><th>Status</th><th>Oferty (top 3)</th></tr></thead>
|
<thead><tr><th>Domena</th><th>TLD</th><th>Score</th><th>LLM</th><th>Status</th><th>Oferty (top 3)</th></tr></thead>
|
||||||
<tbody id="rows"></tbody>
|
<tbody id="rows"></tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@ -133,9 +133,11 @@ function renderRows(){
|
|||||||
}).join('')
|
}).join('')
|
||||||
: `<span class='muted'>Brak danych cenowych dla .${d.tld}</span>`;
|
: `<span class='muted'>Brak danych cenowych dla .${d.tld}</span>`;
|
||||||
|
|
||||||
|
const llm = (d.llm_score!==null && d.llm_score!==undefined) ? `${Number(d.llm_score).toFixed(1)} ${d.decision ? `(${d.decision})` : ''}` : '—';
|
||||||
tr.innerHTML = `<td><a href='${checkUrl}' target='_blank'><b>${d.domain}</b></a> ${d.is_new ? `<span class='chip'>NEW</span>` : ''}</td>
|
tr.innerHTML = `<td><a href='${checkUrl}' target='_blank'><b>${d.domain}</b></a> ${d.is_new ? `<span class='chip'>NEW</span>` : ''}</td>
|
||||||
<td>.${d.tld}</td>
|
<td>.${d.tld}</td>
|
||||||
<td>${d.score}</td>
|
<td>${d.score}</td>
|
||||||
|
<td>${llm}</td>
|
||||||
<td>${d.status || 'available'}</td>
|
<td>${d.status || 'available'}</td>
|
||||||
<td>${offersHtml}</td>`;
|
<td>${offersHtml}</td>`;
|
||||||
rows.appendChild(tr);
|
rows.appendChild(tr);
|
||||||
|
|||||||
11
init_db.py
11
init_db.py
@ -37,6 +37,17 @@ CREATE TABLE IF NOT EXISTS registrar_prices (
|
|||||||
updated_at TEXT,
|
updated_at TEXT,
|
||||||
UNIQUE(registrar, tld)
|
UNIQUE(registrar, tld)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS llm_scores (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
run_id TEXT,
|
||||||
|
domain TEXT,
|
||||||
|
llm_score REAL,
|
||||||
|
decision TEXT,
|
||||||
|
reason TEXT,
|
||||||
|
updated_at TEXT,
|
||||||
|
UNIQUE(run_id, domain)
|
||||||
|
);
|
||||||
''')
|
''')
|
||||||
con.commit()
|
con.commit()
|
||||||
con.close()
|
con.close()
|
||||||
|
|||||||
@ -96,6 +96,16 @@ def main():
|
|||||||
updated_at TEXT,
|
updated_at TEXT,
|
||||||
UNIQUE(registrar, tld)
|
UNIQUE(registrar, tld)
|
||||||
);
|
);
|
||||||
|
CREATE TABLE IF NOT EXISTS llm_scores (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
run_id TEXT,
|
||||||
|
domain TEXT,
|
||||||
|
llm_score REAL,
|
||||||
|
decision TEXT,
|
||||||
|
reason TEXT,
|
||||||
|
updated_at TEXT,
|
||||||
|
UNIQUE(run_id, domain)
|
||||||
|
);
|
||||||
''')
|
''')
|
||||||
|
|
||||||
run_id = latest.get('runId')
|
run_id = latest.get('runId')
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user