tools-update-cron: sync 2026-08-30 — 9 skill(s) updated
This commit is contained in:
@@ -1,19 +1,44 @@
|
||||
---
|
||||
name: youtube-knowledge-ingestion
|
||||
description: "Use when user drops a YouTube link. Transcript→brain→NAS."
|
||||
version: 1.0.0
|
||||
description: "AUTO-TRIGGER: If the operator's message consists solely of a YouTube URL (youtube.com/watch, youtu.be, youtube.com/shorts — no other words), ALWAYS run the full ingestion flow immediately, without asking any clarifying questions: 1. Verbatim transcript → ai_vault_kb (the vault) per the \"Transcript Ingestion (verbatim)\" section (dedup-first, separate doc if a recipe/summary doc for the video already exists). 2. Distilled summary → Cognee brain (the brain) per the \"Brain Injection (Cognee)\" section. 3. If the video's description or pinned comment links a workflow or downloadable assets, download them to the NAS stock library per the existing procedure. 4. Reply with a minimal 4-line completion status (Brain ingest / Vault ingest / Workflow dl / Workflow(s)); write the full proof report (doc_id, chunk count, excerpt, BM25 outputs, file paths + sizes) to ~/workspace/general/logs/yt_ingestion_proofs.log instead of sending it to the operator. Use when user drops a YouTube link. Transcript→vault+brain→NAS."
|
||||
version: 1.1.0
|
||||
platforms: [linux]
|
||||
---
|
||||
|
||||
# YouTube Knowledge Ingestion Pipeline
|
||||
|
||||
## AUTO-TRIGGER (read first — highest priority)
|
||||
|
||||
AUTO-TRIGGER: If the operator's message consists solely of a YouTube URL
|
||||
(youtube.com/watch, youtu.be, youtube.com/shorts — no other words), ALWAYS run the full
|
||||
ingestion flow immediately, without asking any clarifying questions:
|
||||
1. Verbatim transcript → ai_vault_kb (the vault) per the "Transcript Ingestion (verbatim)"
|
||||
section (dedup-first, separate doc if a recipe/summary doc for the video already exists).
|
||||
2. Distilled summary → Cognee brain (the brain) per the "Brain Injection (Cognee)"
|
||||
section.
|
||||
3. If the video's description or pinned comment links a workflow or downloadable assets,
|
||||
download them to the NAS stock library per the existing procedure.
|
||||
4. Reply with a minimal 4-line completion status (see "Completion output" below); write
|
||||
the full proof report to ~/workspace/general/logs/yt_ingestion_proofs.log instead of
|
||||
sending it to the operator.
|
||||
|
||||
**The failure mode this trigger exists to prevent (recurring user correction):**
|
||||
loading the `youtube-content` skill and producing a chat summary. A bare URL is NOT a
|
||||
request for a summary — it is a request to run THIS pipeline. Do NOT load
|
||||
`youtube-content` for a bare URL; load THIS skill (`youtube-knowledge-ingestion`).
|
||||
Do NOT summarize the video in chat under any circumstances. The user has corrected
|
||||
this multiple times ("WHY DO YOU KEEP DOING THIS — YOU HAVE A YT INGEST SKILL").
|
||||
The two skills are easy to confuse: `youtube-content` = fetch transcript + format
|
||||
(summary/thread/blog); `youtube-knowledge-ingestion` = the full transcript→vault +
|
||||
summary→brain + workflow→NAS pipeline. A bare URL always means the latter.
|
||||
|
||||
## When to use
|
||||
|
||||
User drops a YouTube link for AI/ML video content (ComfyUI workflows, LTX, MiniMax,
|
||||
Krea, model tutorials, prompting guides). Run the full three-step pipeline — never skip
|
||||
Krea, model tutorials, prompting guides). Run the full four-step pipeline — never skip
|
||||
any step.
|
||||
|
||||
## Pipeline (always all three steps)
|
||||
## Pipeline (always all four steps)
|
||||
|
||||
### 1. Transcript
|
||||
|
||||
@@ -25,16 +50,16 @@ uv run python3 <SKILL_DIR>/scripts/fetch_transcript.py "URL" --text-only --times
|
||||
|
||||
If `youtube-transcript-api` is missing, install with `pip3 install --user youtube-transcript-api`.
|
||||
|
||||
### 2. Brain Injection (MANDATORY)
|
||||
### 2. Vault Injection (ai_vault_kb) (MANDATORY)
|
||||
|
||||
Load the `ai-brain-kb` skill. Always dedup-first, then ingest:
|
||||
Load the `ai-vault-kb` skill. Always dedup-first, then ingest:
|
||||
|
||||
```bash
|
||||
# Dedup check
|
||||
python3 /home/n8n/bin/ai_brain_kb.py search --query "<key topic>" --limit 5
|
||||
python3 /home/n8n/bin/ai_vault_kb.py search --query "<key topic>" --limit 5
|
||||
|
||||
# Ingest — use --type workflow for tutorials
|
||||
python3 /home/n8n/bin/ai_brain_kb.py add \
|
||||
python3 /home/n8n/bin/ai_vault_kb.py add \
|
||||
--type workflow \
|
||||
--title "Descriptive Title — Key Topics" \
|
||||
--stage <t2v|i2v|upscale|...> \
|
||||
@@ -48,7 +73,7 @@ python3 /home/n8n/bin/ai_brain_kb.py add \
|
||||
--json
|
||||
|
||||
# Verify BM25 leg
|
||||
python3 /home/n8n/bin/ai_brain_kb.py search --query "<distinctive phrase>" \
|
||||
python3 /home/n8n/bin/ai_vault_kb.py search --query "<distinctive phrase>" \
|
||||
--mode bm25 --doc-id <doc_id>
|
||||
```
|
||||
|
||||
@@ -56,7 +81,7 @@ python3 /home/n8n/bin/ai_brain_kb.py search --query "<distinctive phrase>" \
|
||||
Include specific settings, model names, thresholds, commands, and failure modes.
|
||||
This is a technical reference, not a blog post.
|
||||
|
||||
**MANDATORY: workflow links in the brain content.** Every brain entry must include a
|
||||
**MANDATORY: workflow links in the vault content.** Every vault entry must include a
|
||||
`## WORKFLOW LINKS` section listing the DOWNLOADED workflow files on NAS (TrueNAS
|
||||
10.0.0.117, proxmoxBackup/ai_vid_stock_material/workflows/, exact filenames + the
|
||||
smbclient get command), the source repo URL, and the video URL. The NAS copies are
|
||||
@@ -68,7 +93,54 @@ already ingested.
|
||||
**Tag strategy**: model name, tool name, creator name, key techniques. Tags are
|
||||
exact-match keyword indexes.
|
||||
|
||||
### 3. NAS Workflow Download
|
||||
### 3. Brain Injection (Cognee) (MANDATORY)
|
||||
|
||||
Load the `cognee-brain` skill. Write the distilled summary to the shared Cognee
|
||||
brain (10.0.0.23) as a narrative finding — LLM extraction pulls out the entities
|
||||
(models, tools, creators) and facts (claims, settings, comparisons) automatically:
|
||||
|
||||
Call the Cognee MCP tool `mcp__cognee__remember` with:
|
||||
- `data` = the distilled summary (2-4 sentences)
|
||||
- `dataset_name` = `homelab-stack`
|
||||
- omit `session_id` (permanent memory — runs add + cognify, builds the graph)
|
||||
|
||||
- `remember` is synchronous (`status: completed` means the graph is built). No
|
||||
polling needed; verify later with `recall` if needed.
|
||||
- Always use dataset `homelab-stack` (the single shared brain dataset). Never
|
||||
create a second dataset.
|
||||
- The brain holds the distilled facts; the vault (ai_vault_kb) holds the verbatim
|
||||
transcript. Both are written for every video — never skip either.
|
||||
|
||||
**MCP timeout + REST fallback (learned 2026-08-29).** The MCP `remember` call can
|
||||
fail with `TimeoutError: MCP call timed out after 120.0s` because cognify is
|
||||
variable — the REST path took 77s for a 6-item ingest, while MCP full-size payloads
|
||||
ran 9.8–12.2s. The MCP server itself is healthy; it is the client-side 120s
|
||||
per-tool-call timeout that aborts slow cognify runs. Two-part fix:
|
||||
|
||||
1. **Raise the timeout** in `~/.hermes/profiles/general/config.yaml` (cognee MCP
|
||||
block): `timeout: 120` → `timeout: 300`. Takes effect on next Hermes restart
|
||||
(MCP connections are read once at startup). Note: the `patch` tool refuses to
|
||||
edit Hermes config files — use terminal Python for an exact string replace, then
|
||||
`python3 -c "import yaml; yaml.safe_load(open('config.yaml'))"` to validate.
|
||||
2. **REST fallback** when MCP times out (documented in the `cognee-brain` skill):
|
||||
|
||||
```bash
|
||||
# Write (synchronous; returns status:completed + items_processed)
|
||||
curl -s -m 300 -X POST "http://10.0.0.23:8080/api/v1/remember" \
|
||||
-F "data=@/tmp/brain_summary.txt" \
|
||||
-F "datasetName=homelab-stack"
|
||||
|
||||
# Verify (field names are query + searchType, NOT query_text/query_type)
|
||||
curl -s -m 60 -X POST "http://10.0.0.23:8080/api/v1/search" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query":"<distinctive phrase>","datasets":["homelab-stack"],"searchType":"HYBRID_COMPLETION"}'
|
||||
```
|
||||
|
||||
A `status: completed` from the REST write is proof the graph is built — no separate
|
||||
cognify step. If the MCP call times out, do NOT retry it blindly; use the REST path
|
||||
and verify with the search call above.
|
||||
|
||||
### 4. NAS Workflow Download
|
||||
|
||||
If the video description contains workflow links (GitHub repos, direct JSON files),
|
||||
extract the description with `yt-dlp --print description "URL"`, clone the repos,
|
||||
@@ -92,15 +164,171 @@ Examples: `amao2001-ltx2.5-video_ltx2_5_t2v1.json`, `vionex-krea2-film-studio-v0
|
||||
|
||||
**Target**: `proxmoxBackup/ai_vid_stock_material/workflows/` on TrueNAS (10.0.0.117).
|
||||
|
||||
**ComfyUI custom-node repos (no workflow JSONs) → `scripts/`, not `workflows/`.**
|
||||
When the description links a ComfyUI custom-node pack (e.g. PlagueKind's
|
||||
`ComfyUI-PlagueKind-Nodes` — the SLA attention node), the repo is Python source with
|
||||
no `example_workflows/*.json` to copy. Archive it as a tarball under
|
||||
`ai_vid_stock_material/scripts/` (same pattern as full apps — see
|
||||
`references/fetch-path-and-walled-links.md`):
|
||||
|
||||
```bash
|
||||
cd /tmp && rm -rf <repo> && git clone --depth 1 <repo-url>
|
||||
COMMIT=$(cd <repo> && git log -1 --format=%h)
|
||||
tar czf <creator>-<repo>-<commit>.tar.gz <repo>
|
||||
smbclient -N //10.0.0.117/proxmoxBackup \
|
||||
-c 'cd ai_vid_stock_material/scripts; put /tmp/<tarball> <tarball>'
|
||||
```
|
||||
|
||||
`workflows/` stays reserved for ComfyUI JSONs; `scripts/` is the home for node packs
|
||||
and tools. Record the commit hash in the WORKFLOW LINKS section.
|
||||
|
||||
## Transcript Ingestion (verbatim) — when the task says "transcript"
|
||||
|
||||
When the task asks for the TRANSCRIPT (not a summary/recipe), the vault doc must contain
|
||||
the verbatim spoken text. A distilled recipe summary is NOT a transcript.
|
||||
|
||||
**Omit useless segments.** "Verbatim" means the informative spoken content word-for-word —
|
||||
not the filler around it. Cut entirely: sponsor reads / ad segments, song lyrics and
|
||||
music-only passages, giveaway/merch/Patreon plugs, like-and-subscribe boilerplate, and
|
||||
unrelated channel promo. Replace each cut with a one-line marker at that spot — [sponsor
|
||||
segment omitted], [music omitted], [channel promo omitted] — so the cut is visible and
|
||||
auditable. When in doubt, keep it: anything touching the technical content (settings,
|
||||
models, node names, reasoning, results) is never filler, even if it sounds chatty. The
|
||||
word count in the summary header notes omissions, e.g. "2,140 words (3 segments omitted: 2
|
||||
sponsor, 1 music)."
|
||||
|
||||
1. **Fetch the caption track**: `yt-dlp --skip-download --write-auto-subs --write-subs
|
||||
--sub-langs "en.*" <url>` (fall back to `--sub-langs en` if needed). Clean the VTT/SRT
|
||||
to plain text: strip WEBVTT headers, cue timestamps, and inline `<c>`/timestamp tags;
|
||||
dedupe rolling-caption repeated lines. Result must read as continuous spoken sentences.
|
||||
2. **Body layout**: short distilled summary header (10–15 lines max) at top, then the FULL
|
||||
verbatim transcript. Title pattern: `YT: <video title> (<video-id>) — transcript`.
|
||||
Use `--type research` (house pattern for video transcripts), `--trust community`,
|
||||
`--url <video-url>`, tags including the video id.
|
||||
3. **Helper only**: `python3 /home/n8n/bin/ai_vault_kb.py add ...` — never raw Qdrant HTTP
|
||||
(bare-vector upserts miss the BM25 sparse slot and are invisible to hybrid search).
|
||||
4. **Dedup first**: `search --query "<video-id>"`; ≥0.85 skip · 0.70–0.84 add only if
|
||||
meaningfully new · <0.70 add. If a summary/recipe doc for the same video already exists,
|
||||
add the transcript as a SEPARATE doc and mention the other doc_id in the body — do not
|
||||
overwrite the recipe doc.
|
||||
5. **Chunk boundaries + ordering**: the helper chunks at 1200 chars with 150 overlap, and
|
||||
overlap starts land mid-word. To guarantee no chunk starts/ends mid-word, pre-split the
|
||||
body at sentence boundaries into ≤1200-char pieces and add them sequentially with
|
||||
`--doc-id` (each piece ≤1200 chars becomes exactly one chunk). Pass `--chunk-index N`
|
||||
(0-based) on every add-call so reading order is recoverable from metadata: the summary
|
||||
header piece is `--chunk-index 0`, the next piece `--chunk-index 1`, and so on through
|
||||
the transcript body; the WORKFLOW LINKS piece is the last (highest) index. Prefer the
|
||||
bundled `scripts/ingest_transcript.py` — it does the pre-split, the sequential indexed
|
||||
adds, and the self-QA gate in one run. See `references/transcript-ingestion-detail.md`
|
||||
for the chunking algorithm, the `--chunk-index` backfill context, and the proof-log
|
||||
entry format.
|
||||
6. **Self-QA gate before reporting done (mandatory)**:
|
||||
- get the doc back; confirm the body contains verbatim spoken sentences (first-person
|
||||
narration, not bullets);
|
||||
- confirm no chunk begins or ends mid-word (print first/last 10 chars of every chunk);
|
||||
- run a search on one distinctive literal phrase copied from the body and confirm the
|
||||
doc surfaces (proves the BM25 slot).
|
||||
- **chunk-index ordering**: run `list --doc-id <id> --json` and confirm the
|
||||
`chunk_index` values are exactly 0 through N−1, each appearing once. Then read the
|
||||
pieces back in index order and confirm they reproduce the narrative sequence
|
||||
(summary header → transcript body → WORKFLOW LINKS). A doc with duplicate or missing
|
||||
indices fails the gate — fix it by rebuilding the doc: delete --doc-id <id> --yes,
|
||||
then re-add ALL pieces in order with correct --chunk-index values (add --doc-id
|
||||
appends — re-adding a single piece would duplicate it), then re-run this gate.
|
||||
7. **Completion report → log file, not chat.** Do NOT send the proof report to the
|
||||
operator. Instead append it to `~/workspace/general/logs/yt_ingestion_proofs.log`
|
||||
(create the dir if needed) under a dated header per run. The log entry contains the
|
||||
same content as before: doc_id, chunk count, a 2–3 line verbatim excerpt, the BM25
|
||||
search outputs, the chunk-index ordering check output (the `list --doc-id <id> --json`
|
||||
result showing chunk_index 0..N−1 each once), and every downloaded file's full NAS
|
||||
path + size. Then reply to the operator with only the minimal 4-line status per the
|
||||
"Completion output" section below.
|
||||
|
||||
## Completion output (minimal — replaces the chat proof report)
|
||||
|
||||
After a run, reply to the operator with EXACTLY these four lines and nothing more:
|
||||
|
||||
```
|
||||
Brain ingest: done
|
||||
Vault ingest: done
|
||||
Workflow dl: done
|
||||
Workflow(s): <filename(s) as saved on the NAS>
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
1. **"done" is earned, not assumed.** A line may say "done" only after its self-QA gate
|
||||
actually passed — the internal checks (verbatim verify, chunk edges, BM25 probe, NAS
|
||||
size verify) still run in full; only the reporting shrinks. If a step failed or was
|
||||
skipped, say so on that line in a few plain words instead of "done":
|
||||
- Brain ingest: failed — <one-line reason>
|
||||
- Vault ingest: failed — <one-line reason>
|
||||
- Workflow dl: none linked
|
||||
- Workflow(s): <none, or the filenames if some succeeded>
|
||||
2. **Full proof report goes to the log file**, not chat:
|
||||
`~/workspace/general/logs/yt_ingestion_proofs.log` (create the dir if needed). Append
|
||||
one entry per run with a dated header (e.g. `## 2026-08-17 BjZvVx6sDmE — TaoofAI EP.1`)
|
||||
containing: doc_id, chunk count, verbatim excerpt, BM25 search outputs, and every
|
||||
downloaded file's full NAS path + size. This log path is the single place any
|
||||
validator looks for proof.
|
||||
3. **Keep the doc_id available.** Include it in the log entry. If the operator or a
|
||||
validator asks "doc id?" after a run, answer with just the doc_id — nothing else.
|
||||
|
||||
## Hard rules for vault docs created from videos
|
||||
|
||||
- **Every doc created from a video MUST carry the video-ID tag** (e.g. `ZUzeM9OEJ4Y`)
|
||||
in `--tags`, on every chunk-add call. The video ID also goes in `--url` (source_url).
|
||||
- **Additionally ensure the video ID appears in each doc's TITLE** (append `(VIDEOID)` if
|
||||
absent) — tags don't feed BM25, so the tag alone doesn't make the doc rank; title
|
||||
placement does. The transcript title pattern already complies; older recipe/workflow
|
||||
docs won't.
|
||||
- **Trust enum**: `official` | `github` | `community` | `social` — video-derived docs use
|
||||
`--trust community` unless the creator is the model vendor.
|
||||
- **Keyword-search caveat**: the helper builds the BM25 sparse vector from title+text
|
||||
ONLY — tags are payload-only and do not feed keyword search. A doc whose title and
|
||||
body lack the video ID will rank low in `search --query "<video-id>"` even with the
|
||||
tag present. For transcript docs the title pattern `YT: <title> (<video-id>) —
|
||||
transcript` already embeds the ID; for recipe/summary docs, include the video ID in
|
||||
the body (e.g. the WORKFLOW LINKS section) so at least one chunk matches.
|
||||
|
||||
## Hard rules for brain writes created from videos
|
||||
|
||||
- **Every video writes to the brain via `mcp__cognee__remember`** (narrative finding)
|
||||
with `dataset_name="homelab-stack"`. The video URL goes in the data text so the
|
||||
brain fact is traceable back to the video.
|
||||
- **The brain write is the distilled summary, not the verbatim transcript.** Keep it to
|
||||
2-4 sentences of the durable takeaways (what the video demonstrates, key settings,
|
||||
verdict). The verbatim text lives only in the vault.
|
||||
- **`remember` is synchronous** — `status: completed` means the graph is built. If a
|
||||
validator needs proof, `mcp__cognee__recall` a distinctive phrase.
|
||||
- **`status: completed` is NOT proof the content is retrievable.** A write can return
|
||||
`completed` yet a later recall answers "does not contain information about <terms>".
|
||||
The recall is the real gate: after every brain write, `recall` a distinctive phrase
|
||||
from the summary and confirm the answer actually contains it. If it does not,
|
||||
re-write the summary and re-verify — do NOT report "Brain ingest: done" on
|
||||
`status: completed` alone. See `references/brain-write-verification.md`.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- **Never skip the brain injection step.** The user's memory directive explicitly
|
||||
requires both transcript AND brain injection for every YouTube link.
|
||||
- **Never load `youtube-content` for a bare URL.** The bare-URL trigger means run the
|
||||
full pipeline via THIS skill. Loading `youtube-content` and summarizing in chat is the
|
||||
single most common failure — the user has corrected it repeatedly. If you catch
|
||||
yourself about to produce a chat summary of a video, stop and run the pipeline.
|
||||
- **MCP `recall` uses `search_type` (snake_case), REST uses `searchType` (camelCase).**
|
||||
The `mcp__cognee__recall` tool rejects `searchType` with a pydantic validation error
|
||||
("Unexpected keyword argument searchType") — pass `search_type="HYBRID_COMPLETION"`.
|
||||
The REST `/api/v1/search` endpoint (curl) uses `searchType` in the JSON body. Don't
|
||||
mix them up.
|
||||
- **Never skip the vault injection step.** The user's memory directive explicitly
|
||||
requires both transcript AND vault injection for every YouTube link.
|
||||
- **Never skip the brain injection step.** Every video also writes a distilled finding
|
||||
to the Cognee brain (`mcp__cognee__remember`, dataset `homelab-stack`). Vault =
|
||||
verbatim transcript; brain = distilled facts. Both are mandatory.
|
||||
- **Never skip the BM25 verification.** A write that can't be found via BM25 is
|
||||
effectively invisible — the `ai_brain_kb.py` helper is the only interface that
|
||||
effectively invisible — the `ai_vault_kb.py` helper is the only interface that
|
||||
produces searchable points.
|
||||
- **Don't overwrite existing NAS workflows.** Use creator prefixes to avoid collisions
|
||||
with workflows already in the directory.
|
||||
- **The `youtube-content` and `ai-brain-kb` skills are protected** — load them for
|
||||
reference but don't attempt to patch them. This skill is the integration layer
|
||||
between them.
|
||||
- **The `youtube-content`, `ai-vault-kb`, and `cognee-brain` skills are protected** —
|
||||
load them for reference but don't attempt to patch them. This skill is the integration
|
||||
layer between them.
|
||||
|
||||
Reference in New Issue
Block a user