feat: service inventory, ERP reports, sqlite-vec integration, visualize tool
- Add SERVICE_INVENTORY_V1.0.0.md (25 source-verified tools, 3.7GB) - Add ERP_SELECTION_REPORT.md (Odoo CE vs ERPNext comparison) - Add SFTPGO_ODOO_REPLACEMENT.md (SFTPGo migration plan) - Add SERVICE_GO_GITEA_BUILD.md (Go compiler + Gitea build report) - Add release visualize command (face trace heatmap + identity filter) - Add sqlite-vec integration (160MB SQLite with vec0 vector tables) - Add export_identities.py, export_sqlite.py, render_face_heatmap.py - Add Go, Gitea, Rust/Cargo, Swift, yt-dlp, SQLite, sqlite-vec to service CLI - Fix package to include identities and identity_bindings in data.sql - Update release list to show all deployed video stats - Add V1.0.0 YAML frontmatter to all docs (DOCS_STANDARD compliant)
This commit is contained in:
74
scripts/export_identities.py
Normal file
74
scripts/export_identities.py
Normal file
@@ -0,0 +1,74 @@
|
||||
#!/opt/homebrew/bin/python3.11
|
||||
"""
|
||||
Export identity data for a video UUID as JSON (for offline analysis).
|
||||
Usage: python3 export_identities.py <file_uuid> [output.json]
|
||||
"""
|
||||
import sys, json, psycopg2
|
||||
|
||||
UUID = sys.argv[1] if len(sys.argv) > 1 else "aeed71342a899fe4b4c57b7d41bcb692"
|
||||
OUT = sys.argv[2] if len(sys.argv) > 2 else f"/Users/accusys/momentry/output_dev/{UUID}.identities.json"
|
||||
|
||||
conn = psycopg2.connect("dbname=momentry user=accusys")
|
||||
cur = conn.cursor()
|
||||
|
||||
# Get identities referenced by this file's face_detections
|
||||
cur.execute("""
|
||||
SELECT DISTINCT i.id, i.name, i.uuid, i.identity_type, i.source, i.status,
|
||||
i.face_embedding, i.voice_embedding, i.reference_data, i.tmdb_id, i.tmdb_profile
|
||||
FROM dev.identities i
|
||||
INNER JOIN dev.face_detections fd ON fd.identity_id = i.id
|
||||
WHERE fd.file_uuid = %s
|
||||
ORDER BY i.id
|
||||
""", (UUID,))
|
||||
rows = cur.fetchall()
|
||||
|
||||
identities = []
|
||||
for r in rows:
|
||||
identities.append({
|
||||
"id": r[0],
|
||||
"name": r[1],
|
||||
"uuid": str(r[2]) if r[2] else None,
|
||||
"identity_type": r[3],
|
||||
"source": r[4],
|
||||
"status": r[5],
|
||||
"tmdb_id": r[9],
|
||||
"tmdb_profile": r[10],
|
||||
})
|
||||
|
||||
# Get identity_bindings for these identities' traces
|
||||
cur.execute("""
|
||||
SELECT DISTINCT ib.identity_id, ib.identity_type, ib.identity_value, ib.confidence
|
||||
FROM dev.identity_bindings ib
|
||||
WHERE ib.identity_id IN (
|
||||
SELECT DISTINCT fd.identity_id FROM dev.face_detections fd WHERE fd.file_uuid = %s
|
||||
)
|
||||
""", (UUID,))
|
||||
bindings = [{"identity_id": r[0], "identity_type": r[1], "identity_value": r[2], "confidence": float(r[3])} for r in cur.fetchall()]
|
||||
|
||||
# Get trace-to-identity mapping from face_detections
|
||||
cur.execute("""
|
||||
SELECT DISTINCT trace_id, identity_id, COUNT(*) as face_count
|
||||
FROM dev.face_detections
|
||||
WHERE file_uuid = %s AND identity_id IS NOT NULL AND trace_id IS NOT NULL
|
||||
GROUP BY trace_id, identity_id ORDER BY trace_id
|
||||
""", (UUID,))
|
||||
trace_map = [{"trace_id": r[0], "identity_id": r[1], "face_count": r[2]} for r in cur.fetchall()]
|
||||
|
||||
cur.close(); conn.close()
|
||||
|
||||
output = {
|
||||
"file_uuid": UUID,
|
||||
"identity_count": len(identities),
|
||||
"binding_count": len(bindings),
|
||||
"trace_mapping_count": len(trace_map),
|
||||
"identities": identities,
|
||||
"bindings": bindings,
|
||||
"trace_to_identity": trace_map,
|
||||
}
|
||||
|
||||
with open(OUT, 'w') as f:
|
||||
json.dump(output, f, indent=2, ensure_ascii=False)
|
||||
|
||||
size_kb = len(json.dumps(output)) / 1024
|
||||
print(f"Exported {len(identities)} identities, {len(bindings)} bindings, {len(trace_map)} trace mappings")
|
||||
print(f" → {OUT} ({size_kb:.0f}KB)")
|
||||
Reference in New Issue
Block a user