343 lines
18 KiB
HTML
343 lines
18 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>10 Pipeline - Momentry API Docs</title>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; color: #333; padding: 40px; }
|
|
.container { max-width: 960px; margin: 0 auto; background: white; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.08); padding: 40px; }
|
|
h1 { font-size: 24px; margin: 24px 0 12px; }
|
|
h2 { font-size: 20px; margin: 20px 0 10px; color: #222; }
|
|
h3 { font-size: 16px; margin: 16px 0 8px; color: #444; }
|
|
p { line-height: 1.6; margin: 8px 0; }
|
|
table { border-collapse: collapse; width: 100%; margin: 12px 0; font-size: 14px; }
|
|
th, td { border: 1px solid #ddd; padding: 8px 12px; text-align: left; }
|
|
th { background: #f0f0f0; font-weight: 600; }
|
|
code { background: #f0f0f0; padding: 2px 6px; border-radius: 3px; font-size: 13px; }
|
|
pre { background: #f8f8f8; border: 1px solid #ddd; border-radius: 6px; padding: 12px; overflow-x: auto; margin: 12px 0; }
|
|
pre code { background: none; padding: 0; }
|
|
a { color: #0066cc; }
|
|
.back { display: inline-block; margin-bottom: 20px; color: #666; }
|
|
.back:hover { color: #333; }
|
|
.topbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
|
|
.logout-btn { font-size: 13px; color: #999; text-decoration: none; }
|
|
.logout-btn:hover { color: #cc0000; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="topbar">
|
|
<a class="back" href="index.html">← Back to index</a>
|
|
<a class="logout-btn" href="#" onclick="fetch('/api/v1/auth/logout',{method:'POST'}).then(()=>window.location.reload());return false">Logout</a>
|
|
</div>
|
|
<!-- module: pipeline -->
|
|
<!-- description: Pipeline processors, ingestion status, stats endpoints -->
|
|
<!-- depends: 01_auth -->
|
|
|
|
<h2>Pipeline</h2>
|
|
<h3>Pipeline Completion Flow</h3>
|
|
<p>The pipeline is <strong>not complete</strong> until both the 10 processors AND the 入庫 (ingestion) steps have finished. The worker polls every 3 seconds and only marks the job as <code>completed</code> when all ingestion steps verify OK.</p>
|
|
<div class="codehilite"><pre><span></span><code><span class="mf">10</span><span class="w"> </span><span class="n">processors</span><span class="w"> </span><span class="n">done</span>
|
|
<span class="w"> </span><span class="err">↓</span><span class="w"> </span><span class="p">(</span><span class="n">job</span><span class="w"> </span><span class="n">status</span><span class="w"> </span><span class="n">stays</span><span class="w"> </span><span class="s">"running"</span><span class="p">)</span>
|
|
<span class="n">Algorithm</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="n">Trigger</span><span class="p">:</span><span class="w"> </span><span class="n">Rule</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">Vectorize</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">Phase</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="n">Pack</span>
|
|
<span class="w"> </span><span class="err">↓</span><span class="w"> </span><span class="p">(</span><span class="n">job</span><span class="w"> </span><span class="kr">run</span><span class="n">s</span><span class="w"> </span><span class="n">in</span><span class="w"> </span><span class="n">parallel</span><span class="p">)</span>
|
|
<span class="n">Algorithm</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="n">Trigger</span><span class="p">:</span><span class="w"> </span><span class="n">Face</span><span class="w"> </span><span class="n">Trace</span><span class="w"> </span><span class="err">→</span><span class="w"> </span><span class="n">TKG</span><span class="p">,</span><span class="w"> </span><span class="n">Scene</span><span class="w"> </span><span class="n">Metadata</span><span class="p">,</span><span class="w"> </span><span class="n">Identity</span><span class="w"> </span><span class="n">Agent</span><span class="p">,</span><span class="w"> </span><span class="mf">5</span><span class="n">W1H</span><span class="w"> </span><span class="n">Agent</span>
|
|
<span class="w"> </span><span class="err">↓</span><span class="w"> </span><span class="p">(</span><span class="n">poll</span><span class="w"> </span><span class="n">checks</span><span class="w"> </span><span class="n">every</span><span class="w"> </span><span class="mf">3</span><span class="n">s</span><span class="p">)</span>
|
|
<span class="n">Ingestion</span><span class="w"> </span><span class="n">verification</span><span class="p">:</span><span class="w"> </span><span class="n">rule1</span><span class="w"> </span><span class="err">✓</span><span class="w"> </span><span class="n">vectorize</span><span class="w"> </span><span class="err">✓</span><span class="w"> </span><span class="n">rule3</span><span class="w"> </span><span class="err">✓</span><span class="w"> </span><span class="n">face_trace</span><span class="w"> </span><span class="err">✓</span><span class="w"> </span><span class="n">tkg</span><span class="w"> </span><span class="err">✓</span><span class="w"> </span><span class="n">scene_meta</span><span class="w"> </span><span class="err">✓</span><span class="w"> </span><span class="mf">5</span><span class="n">w1h</span><span class="w"> </span><span class="err">✓</span>
|
|
<span class="w"> </span><span class="err">↓</span>
|
|
<span class="n">job</span><span class="w"> </span><span class="n">status</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"completed"</span>
|
|
</code></pre></div>
|
|
|
|
<h3>10 Processor Stages</h3>
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>#</th>
|
|
<th>Processor</th>
|
|
<th>Depends On</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>1</td>
|
|
<td><code>Cut</code></td>
|
|
<td>—</td>
|
|
<td>Scene boundary detection (PySceneDetect)</td>
|
|
</tr>
|
|
<tr>
|
|
<td>2</td>
|
|
<td><code>ASR</code></td>
|
|
<td>Cut</td>
|
|
<td>Automatic speech recognition (faster-whisper)</td>
|
|
</tr>
|
|
<tr>
|
|
<td>3</td>
|
|
<td><code>ASRX</code></td>
|
|
<td>ASR</td>
|
|
<td>Speaker diarization + ASR refinement</td>
|
|
</tr>
|
|
<tr>
|
|
<td>4</td>
|
|
<td><code>YOLO</code></td>
|
|
<td>—</td>
|
|
<td>Object detection (YOLOv8)</td>
|
|
</tr>
|
|
<tr>
|
|
<td>5</td>
|
|
<td><code>OCR</code></td>
|
|
<td>—</td>
|
|
<td>Optical character recognition</td>
|
|
</tr>
|
|
<tr>
|
|
<td>6</td>
|
|
<td><code>Face</code></td>
|
|
<td>—</td>
|
|
<td>Face detection + recognition (InsightFace + CoreML)</td>
|
|
</tr>
|
|
<tr>
|
|
<td>7</td>
|
|
<td><code>Pose</code></td>
|
|
<td>—</td>
|
|
<td>Pose estimation</td>
|
|
</tr>
|
|
<tr>
|
|
<td>8</td>
|
|
<td><code>VisualChunk</code></td>
|
|
<td>YOLO</td>
|
|
<td>Visual object chunking</td>
|
|
</tr>
|
|
<tr>
|
|
<td>9</td>
|
|
<td><code>Story</code></td>
|
|
<td>ASRX + Cut + YOLO + Face</td>
|
|
<td>Narrative scene summarization (LLM, with embedding)</td>
|
|
</tr>
|
|
<tr>
|
|
<td>10</td>
|
|
<td><code>5W1H</code></td>
|
|
<td>Story</td>
|
|
<td>Who/What/When/Where/Why extraction (LLM, with embedding)</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<h3>入庫 (Post-Processing / Ingestion)</h3>
|
|
<p>These steps run after the 10 processors and are <strong>required for pipeline completion</strong>. The worker checks all of them before marking the job as done.</p>
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>#</th>
|
|
<th>Step</th>
|
|
<th>Triggers When</th>
|
|
<th>Verification</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>1</td>
|
|
<td><strong>Rule 1 Sentence Chunking</strong></td>
|
|
<td>ASR + ASRX done</td>
|
|
<td><code>chunk</code> table has rows with <code>chunk_type = 'sentence'</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td>2</td>
|
|
<td><strong>Auto-Vectorize</strong></td>
|
|
<td>Rule 1 done</td>
|
|
<td><code>chunk.embedding</code> IS NOT NULL for sentence chunks</td>
|
|
</tr>
|
|
<tr>
|
|
<td>3</td>
|
|
<td><strong>Phase 1 Pack</strong></td>
|
|
<td>Rule 1 done</td>
|
|
<td><code>release_pack.py --phase 1</code> executed</td>
|
|
</tr>
|
|
<tr>
|
|
<td>4</td>
|
|
<td><strong>Rule 3 Scene Chunking</strong></td>
|
|
<td>All 10 processors done + Cut + ASR</td>
|
|
<td><code>chunk</code> table has rows with <code>chunk_type = 'cut'</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td>5</td>
|
|
<td><strong>Face Trace</strong></td>
|
|
<td>All 10 processors done + Face</td>
|
|
<td><code>face_detections.trace_id</code> IS NOT NULL</td>
|
|
</tr>
|
|
<tr>
|
|
<td>6</td>
|
|
<td><strong>Qdrant Face Sync</strong></td>
|
|
<td>Face Trace done</td>
|
|
<td>Qdrant face_embedding collection populated</td>
|
|
</tr>
|
|
<tr>
|
|
<td>7</td>
|
|
<td><strong>Trace Chunks</strong></td>
|
|
<td>Face Trace done</td>
|
|
<td><code>chunk</code> table has rows with <code>chunk_type = 'trace'</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td>8</td>
|
|
<td><strong>TKG Builder</strong></td>
|
|
<td>Face Trace done</td>
|
|
<td><code>tkg_nodes</code> + <code>tkg_edges</code> tables have rows</td>
|
|
</tr>
|
|
<tr>
|
|
<td>9</td>
|
|
<td><strong>TMDb Face Matching</strong></td>
|
|
<td>TMDb enabled + Face done</td>
|
|
<td><code>face_detections.identity_id</code> IS NOT NULL</td>
|
|
</tr>
|
|
<tr>
|
|
<td>10</td>
|
|
<td><strong>Heuristic Scene Metadata</strong></td>
|
|
<td>Face + YOLO done</td>
|
|
<td><code>{file_uuid}.scene_meta.json</code> exists on disk</td>
|
|
</tr>
|
|
<tr>
|
|
<td>11</td>
|
|
<td><strong>Template 5W1H Story Summary (PG)</strong></td>
|
|
<td>Story done</td>
|
|
<td><code>chunk.embedding</code> IS NOT NULL for story chunks</td>
|
|
</tr>
|
|
<tr>
|
|
<td>12</td>
|
|
<td><strong>LLM 5W1H Summary (PG)</strong></td>
|
|
<td>5W1H done</td>
|
|
<td><code>chunk.embedding</code> IS NOT NULL for llm chunks</td>
|
|
</tr>
|
|
<tr>
|
|
<td>13</td>
|
|
<td><strong>Voice Embedding (Qdrant)</strong></td>
|
|
<td>ASRX done</td>
|
|
<td>Qdrant voice collection populated</td>
|
|
</tr>
|
|
<tr>
|
|
<td>14</td>
|
|
<td><strong>Face Embedding (Qdrant)</strong></td>
|
|
<td>Face done</td>
|
|
<td>Qdrant face collection populated</td>
|
|
</tr>
|
|
<tr>
|
|
<td>15</td>
|
|
<td><strong>Identity Agent</strong></td>
|
|
<td>Face + ASRX done</td>
|
|
<td><code>identities</code> with <code>source = 'identity_agent'</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td>16</td>
|
|
<td><strong>5W1H Agent</strong></td>
|
|
<td>Cut + ASR done</td>
|
|
<td><code>chunk.summary_text</code> IS NOT NULL for cut chunks</td>
|
|
</tr>
|
|
<tr>
|
|
<td>17</td>
|
|
<td><strong>Release Pack</strong></td>
|
|
<td>5W1H Agent done</td>
|
|
<td><code>release_pack.py --phase 2</code> executed</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<h3>Ingestion Status</h3>
|
|
<p>Check real-time ingestion status for a file:</p>
|
|
<div class="codehilite"><pre><span></span><code>curl<span class="w"> </span><span class="s2">"</span><span class="nv">$API</span><span class="s2">/api/v1/stats/ingestion-status/{file_uuid}"</span>
|
|
</code></pre></div>
|
|
|
|
<p>Returns per-step <code>done</code> / <code>pending</code> status with detail counts.</p>
|
|
<h4>Example</h4>
|
|
<div class="codehilite"><pre><span></span><code>curl<span class="w"> </span><span class="s2">"http://localhost:3003/api/v1/stats/ingestion-status/bd80fec9c42afb0307eb28f22c64c76a"</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>jq<span class="w"> </span><span class="s1">'.steps[] | {name, status, detail}'</span>
|
|
</code></pre></div>
|
|
|
|
<h4>Response</h4>
|
|
<div class="codehilite"><pre><span></span><code><span class="p">{</span>
|
|
<span class="w"> </span><span class="nt">"file_uuid"</span><span class="p">:</span><span class="w"> </span><span class="s2">"bd80fec9c42afb0307eb28f22c64c76a"</span><span class="p">,</span>
|
|
<span class="w"> </span><span class="nt">"steps"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
|
|
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"rule1_sentence"</span><span class="p">,</span><span class="w"> </span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"pending"</span><span class="p">,</span><span class="w"> </span><span class="nt">"detail"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0 sentence chunks"</span><span class="w"> </span><span class="p">},</span>
|
|
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"auto_vectorize"</span><span class="p">,</span><span class="w"> </span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"pending"</span><span class="p">,</span><span class="w"> </span><span class="nt">"detail"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0 embedded"</span><span class="w"> </span><span class="p">},</span>
|
|
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"rule3_scene"</span><span class="p">,</span><span class="w"> </span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"pending"</span><span class="p">,</span><span class="w"> </span><span class="nt">"detail"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0 scene chunks"</span><span class="w"> </span><span class="p">},</span>
|
|
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"face_trace"</span><span class="p">,</span><span class="w"> </span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"pending"</span><span class="p">,</span><span class="w"> </span><span class="nt">"detail"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0 traces"</span><span class="w"> </span><span class="p">},</span>
|
|
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"trace_chunks"</span><span class="p">,</span><span class="w"> </span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"pending"</span><span class="p">,</span><span class="w"> </span><span class="nt">"detail"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0 trace chunks"</span><span class="w"> </span><span class="p">},</span>
|
|
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"tkg"</span><span class="p">,</span><span class="w"> </span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"pending"</span><span class="p">,</span><span class="w"> </span><span class="nt">"detail"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0 nodes, 0 edges"</span><span class="w"> </span><span class="p">},</span>
|
|
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"identity_match"</span><span class="p">,</span><span class="w"> </span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"pending"</span><span class="p">,</span><span class="w"> </span><span class="nt">"detail"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0 identities"</span><span class="w"> </span><span class="p">},</span>
|
|
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"scene_metadata"</span><span class="p">,</span><span class="w"> </span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"pending"</span><span class="p">,</span><span class="w"> </span><span class="nt">"detail"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="p">},</span>
|
|
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"5w1h"</span><span class="p">,</span><span class="w"> </span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"pending"</span><span class="p">,</span><span class="w"> </span><span class="nt">"detail"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0 scenes with 5W1H"</span><span class="w"> </span><span class="p">}</span>
|
|
<span class="w"> </span><span class="p">]</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
|
|
<h3>Stats Endpoints</h3>
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Method</th>
|
|
<th>Endpoint</th>
|
|
<th>Auth</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>GET</td>
|
|
<td><code>/api/v1/stats/sftpgo</code></td>
|
|
<td>No</td>
|
|
<td>SFTPGo service status</td>
|
|
</tr>
|
|
<tr>
|
|
<td>GET</td>
|
|
<td><code>/api/v1/stats/ingestion-status/:file_uuid</code></td>
|
|
<td>No</td>
|
|
<td>Per-file ingestion checklist</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<h3>Configuration</h3>
|
|
<p>See <a href="13_config.md">13_config.md</a> for runtime configuration endpoints:</p>
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Endpoint</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><code>POST /api/v1/config/cache</code></td>
|
|
<td>Toggle Redis cache</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>POST /api/v1/config/auto-pipeline</code></td>
|
|
<td>Toggle auto-pipeline on register</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>POST /api/v1/config/watcher-auto-register</code></td>
|
|
<td>Toggle watcher auto-register</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<h3>Unmounted Routes</h3>
|
|
<p>The following routes are defined in source code but are <strong>NOT</strong> currently mounted in the router:</p>
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Endpoint</th>
|
|
<th>Source file</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><code>/api/v1/search/persons</code></td>
|
|
<td><code>universal_search.rs</code> (not mounted)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>/api/v1/who</code></td>
|
|
<td><code>who.rs</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>/api/v1/who/candidates</code></td>
|
|
<td><code>who.rs</code></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</body>
|
|
</html> |