feat(tools-pve/asr-pipeline): SQLite model config, task delete/rerefine, multi-recording review, lexicon CRUD
This commit is contained in:
@@ -298,7 +298,7 @@ def sync_from_vault(force: bool = False) -> dict:
|
||||
now = time.time()
|
||||
n_ent = n_alias = 0
|
||||
con.execute("DELETE FROM alias WHERE origin IN ('card','glossary')")
|
||||
con.execute("DELETE FROM entity")
|
||||
con.execute("DELETE FROM entity WHERE card <> ''")
|
||||
con.execute("DELETE FROM relation WHERE source LIKE 'card:%'")
|
||||
for sub, kind in (("People", "人名"), ("Companies", "公司"), ("Projects", "项目")):
|
||||
d = CFG.vault / sub
|
||||
@@ -524,3 +524,261 @@ def stats() -> dict:
|
||||
d["synced_at"] = r["v"] if r else ""
|
||||
con.close()
|
||||
return d
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ Web UI CRUD
|
||||
def list_aliases(q: str = "", origin_filter: str = "", limit: int = 200) -> list[dict]:
|
||||
con = connect()
|
||||
sql = "SELECT * FROM alias WHERE 1=1"
|
||||
args: list = []
|
||||
if q.strip():
|
||||
pat = f"%{q.strip()}%"
|
||||
sql += " AND (alias LIKE ? OR canonical LIKE ? OR note LIKE ?)"
|
||||
args.extend([pat, pat, pat])
|
||||
if origin_filter == "learned":
|
||||
sql += " AND origin <> 'card'"
|
||||
elif origin_filter == "card":
|
||||
sql += " AND origin = 'card'"
|
||||
sql += " ORDER BY confirmed DESC, created_at DESC, alias ASC LIMIT ?"
|
||||
args.append(limit)
|
||||
rows = [dict(r) for r in con.execute(sql, args).fetchall()]
|
||||
con.close()
|
||||
return rows
|
||||
|
||||
|
||||
def update_alias(
|
||||
old_alias: str,
|
||||
old_canonical: str,
|
||||
new_alias: str,
|
||||
new_canonical: str,
|
||||
*,
|
||||
kind: str = "",
|
||||
confirmed: int = 1,
|
||||
note: str = "",
|
||||
) -> bool:
|
||||
con = connect()
|
||||
row = con.execute(
|
||||
"SELECT * FROM alias WHERE alias=? AND canonical=?",
|
||||
(old_alias, old_canonical),
|
||||
).fetchone()
|
||||
origin = row["origin"] if row else "manual"
|
||||
hits = row["hits"] if row else 0
|
||||
created_at = row["created_at"] if row else time.time()
|
||||
if not kind:
|
||||
er = con.execute("SELECT kind FROM entity WHERE canonical=?", (new_canonical,)).fetchone()
|
||||
kind = er["kind"] if er else (row["kind"] if row else guess_kind(new_canonical))
|
||||
con.execute(
|
||||
"DELETE FROM alias WHERE alias=? AND canonical=?",
|
||||
(old_alias, old_canonical),
|
||||
)
|
||||
con.execute(
|
||||
"INSERT OR REPLACE INTO alias(alias,canonical,kind,origin,confirmed,hits,created_at,note) "
|
||||
"VALUES(?,?,?,?,?,?,?,?)",
|
||||
(new_alias, new_canonical, kind, origin, int(bool(confirmed)), hits, created_at, note),
|
||||
)
|
||||
con.commit()
|
||||
con.close()
|
||||
return True
|
||||
|
||||
|
||||
def delete_alias(alias: str, canonical: str) -> bool:
|
||||
con = connect()
|
||||
cur = con.execute("DELETE FROM alias WHERE alias=? AND canonical=?", (alias, canonical))
|
||||
con.commit()
|
||||
deleted = cur.rowcount > 0
|
||||
con.close()
|
||||
return deleted
|
||||
|
||||
|
||||
def list_corrections(q: str = "", limit: int = 200) -> list[dict]:
|
||||
con = connect()
|
||||
sql = "SELECT * FROM correction WHERE 1=1"
|
||||
args: list = []
|
||||
if q.strip():
|
||||
pat = f"%{q.strip()}%"
|
||||
sql += " AND (surface LIKE ? OR canonical LIKE ? OR note LIKE ?)"
|
||||
args.extend([pat, pat, pat])
|
||||
sql += " ORDER BY confirmed DESC, n DESC, last_seen DESC LIMIT ?"
|
||||
args.append(limit)
|
||||
rows = [dict(r) for r in con.execute(sql, args).fetchall()]
|
||||
con.close()
|
||||
return rows
|
||||
|
||||
|
||||
def update_correction(
|
||||
old_surface: str,
|
||||
old_canonical: str,
|
||||
new_surface: str,
|
||||
new_canonical: str,
|
||||
*,
|
||||
confirmed: int = 1,
|
||||
note: str = "",
|
||||
) -> bool:
|
||||
con = connect()
|
||||
row = con.execute(
|
||||
"SELECT * FROM correction WHERE surface=? AND canonical=?",
|
||||
(old_surface, old_canonical),
|
||||
).fetchone()
|
||||
n = row["n"] if row else 1
|
||||
now = time.time()
|
||||
con.execute("DELETE FROM correction WHERE surface=? AND canonical=?", (old_surface, old_canonical))
|
||||
con.execute(
|
||||
"DELETE FROM phonetic_confusion WHERE heard=? AND intended=?",
|
||||
(old_surface, old_canonical),
|
||||
)
|
||||
con.execute(
|
||||
"INSERT OR REPLACE INTO correction(surface,canonical,n,confirmed,last_seen,note) "
|
||||
"VALUES(?,?,?,?,?,?)",
|
||||
(new_surface, new_canonical, n, int(bool(confirmed)), now, note),
|
||||
)
|
||||
con.execute(
|
||||
"INSERT OR REPLACE INTO phonetic_confusion(heard,intended,n,confirmed,last_seen,note) "
|
||||
"VALUES(?,?,?,?,?,?)",
|
||||
(new_surface, new_canonical, n, int(bool(confirmed)), now, note),
|
||||
)
|
||||
con.commit()
|
||||
con.close()
|
||||
return True
|
||||
|
||||
|
||||
def delete_correction(surface: str, canonical: str) -> bool:
|
||||
con = connect()
|
||||
cur = con.execute("DELETE FROM correction WHERE surface=? AND canonical=?", (surface, canonical))
|
||||
con.execute("DELETE FROM phonetic_confusion WHERE heard=? AND intended=?", (surface, canonical))
|
||||
con.commit()
|
||||
deleted = cur.rowcount > 0
|
||||
con.close()
|
||||
return deleted
|
||||
|
||||
|
||||
def list_entities(q: str = "", kind: str = "", limit: int = 200) -> list[dict]:
|
||||
con = connect()
|
||||
sql = "SELECT * FROM entity WHERE 1=1"
|
||||
args: list = []
|
||||
if q.strip():
|
||||
pat = f"%{q.strip()}%"
|
||||
sql += " AND (canonical LIKE ? OR company LIKE ? OR role LIKE ? OR related LIKE ?)"
|
||||
args.extend([pat, pat, pat, pat])
|
||||
if kind.strip():
|
||||
sql += " AND kind=?"
|
||||
args.append(kind.strip())
|
||||
sql += " ORDER BY (CASE WHEN card='' THEN 0 ELSE 1 END), canonical ASC LIMIT ?"
|
||||
args.append(limit)
|
||||
rows = [dict(r) for r in con.execute(sql, args).fetchall()]
|
||||
con.close()
|
||||
return rows
|
||||
|
||||
|
||||
def upsert_entity(
|
||||
canonical: str,
|
||||
kind: str = "人名",
|
||||
*,
|
||||
company: str = "",
|
||||
role: str = "",
|
||||
related: str = "",
|
||||
card: str = "",
|
||||
) -> None:
|
||||
con = connect()
|
||||
con.execute(
|
||||
"INSERT OR REPLACE INTO entity(canonical,kind,company,role,related,card,synced_at) "
|
||||
"VALUES(?,?,?,?,?,?,?)",
|
||||
(canonical, kind or guess_kind(canonical), company, role, related, card, time.time()),
|
||||
)
|
||||
con.commit()
|
||||
con.close()
|
||||
|
||||
|
||||
def update_entity(
|
||||
old_canonical: str,
|
||||
new_canonical: str,
|
||||
kind: str,
|
||||
*,
|
||||
company: str = "",
|
||||
role: str = "",
|
||||
related: str = "",
|
||||
) -> bool:
|
||||
con = connect()
|
||||
row = con.execute("SELECT * FROM entity WHERE canonical=?", (old_canonical,)).fetchone()
|
||||
card = row["card"] if row else ""
|
||||
con.execute("DELETE FROM entity WHERE canonical=?", (old_canonical,))
|
||||
con.execute(
|
||||
"INSERT OR REPLACE INTO entity(canonical,kind,company,role,related,card,synced_at) "
|
||||
"VALUES(?,?,?,?,?,?,?)",
|
||||
(new_canonical, kind or guess_kind(new_canonical), company, role, related, card, time.time()),
|
||||
)
|
||||
if old_canonical != new_canonical:
|
||||
con.execute("UPDATE alias SET canonical=? WHERE canonical=?", (new_canonical, old_canonical))
|
||||
con.execute("UPDATE correction SET canonical=? WHERE canonical=?", (new_canonical, old_canonical))
|
||||
con.commit()
|
||||
con.close()
|
||||
return True
|
||||
|
||||
|
||||
def delete_entity(canonical: str) -> bool:
|
||||
con = connect()
|
||||
cur = con.execute("DELETE FROM entity WHERE canonical=?", (canonical,))
|
||||
con.commit()
|
||||
deleted = cur.rowcount > 0
|
||||
con.close()
|
||||
return deleted
|
||||
|
||||
|
||||
def list_relations(q: str = "", limit: int = 200) -> list[dict]:
|
||||
con = connect()
|
||||
sql = "SELECT * FROM relation WHERE 1=1"
|
||||
args: list = []
|
||||
if q.strip():
|
||||
pat = f"%{q.strip()}%"
|
||||
sql += " AND (subject LIKE ? OR predicate LIKE ? OR object LIKE ? OR source LIKE ?)"
|
||||
args.extend([pat, pat, pat, pat])
|
||||
sql += " ORDER BY active DESC, confidence DESC, last_seen DESC LIMIT ?"
|
||||
args.append(limit)
|
||||
rows = [dict(r) for r in con.execute(sql, args).fetchall()]
|
||||
con.close()
|
||||
return rows
|
||||
|
||||
|
||||
def update_relation(
|
||||
old_subject: str,
|
||||
old_predicate: str,
|
||||
old_object: str,
|
||||
old_source: str,
|
||||
subject: str,
|
||||
predicate: str,
|
||||
object_: str,
|
||||
*,
|
||||
confidence: float = 0.8,
|
||||
active: int = 1,
|
||||
) -> bool:
|
||||
con = connect()
|
||||
row = con.execute(
|
||||
"SELECT * FROM relation WHERE subject=? AND predicate=? AND object=? AND source=?",
|
||||
(old_subject, old_predicate, old_object, old_source),
|
||||
).fetchone()
|
||||
first_seen = row["first_seen"] if row else time.time()
|
||||
source = old_source or "manual"
|
||||
con.execute(
|
||||
"DELETE FROM relation WHERE subject=? AND predicate=? AND object=? AND source=?",
|
||||
(old_subject, old_predicate, old_object, old_source),
|
||||
)
|
||||
con.execute(
|
||||
"INSERT OR REPLACE INTO relation(subject,predicate,object,confidence,source,first_seen,last_seen,active) "
|
||||
"VALUES(?,?,?,?,?,?,?,?)",
|
||||
(subject, predicate, object_, float(confidence), source, first_seen, time.time(), int(bool(active))),
|
||||
)
|
||||
con.commit()
|
||||
con.close()
|
||||
return True
|
||||
|
||||
|
||||
def delete_relation(subject: str, predicate: str, object_: str, source: str) -> bool:
|
||||
con = connect()
|
||||
cur = con.execute(
|
||||
"DELETE FROM relation WHERE subject=? AND predicate=? AND object=? AND source=?",
|
||||
(subject, predicate, object_, source),
|
||||
)
|
||||
con.commit()
|
||||
deleted = cur.rowcount > 0
|
||||
con.close()
|
||||
return deleted
|
||||
|
||||
|
||||
Reference in New Issue
Block a user