Download scripts/try_generator_prompt.sh from htaf/distill-pipeline: direct link, hf CLI and curl.
- Browser
- Download file 6.12 kB
-
https://huggingface.co/htaf/distill-pipeline/resolve/main/scripts/try_generator_prompt.sh
- Command line
-
hf download hf://htaf/distill-pipeline/scripts/try_generator_prompt.sh
-
curl -L -o try_generator_prompt.sh https://huggingface.co/htaf/distill-pipeline/resolve/main/scripts/try_generator_prompt.sh
6.12 kB
| set -euo pipefail | |
| # Usage: | |
| # scripts/try_generator_prompt.sh [chunk_id] [question_index] [-r] [--random] | |
| # - chunk_id: optional. default = first cached chunk in questions cache | |
| # - question_index: 0-based index into the cached question list for that chunk (default 0) | |
| # - -r / --reasoning: enable Ollama reasoning option | |
| # - --random: pick a random cached chunk and random question (ignores positional args) | |
| # | |
| # Requirements: jq, node, cache populated (data/cache/questions.jsonl) and rag chunks file (data/rag_chunks.jsonl) | |
| CHUNK_ID="" | |
| QUESTION_INDEX=0 | |
| REASONING=0 | |
| RANDOM_MODE=0 | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| -r|--reasoning) | |
| REASONING=1 | |
| shift | |
| ;; | |
| --random) | |
| RANDOM_MODE=1 | |
| shift | |
| ;; | |
| *) | |
| if [[ -z "$CHUNK_ID" ]]; then | |
| CHUNK_ID="$1" | |
| else | |
| QUESTION_INDEX="$1" | |
| fi | |
| shift | |
| ;; | |
| esac | |
| done | |
| ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" | |
| CACHE_DIR="${PIPELINE_CACHE_DIR:-$ROOT_DIR/data/cache}" | |
| QUESTIONS_FILE="${CACHE_DIR}/questions.jsonl" | |
| RAG_PATH="${RAG_CHUNKS_PATH:-$ROOT_DIR/data/rag_chunks.jsonl}" | |
| PROMPT_FILE="${PROMPT_FILE:-$ROOT_DIR/prompts/generator_prompt.txt}" | |
| MODEL="${GENERATOR_MODEL:-${OLLAMA_MODEL:-qwen3-vl:8b-thinking}}" | |
| OLLAMA_URL="${OLLAMA_URL:-http://localhost:11434}" | |
| if [[ ! -f "$QUESTIONS_FILE" ]]; then | |
| echo "❌ questions cache not found at $QUESTIONS_FILE" >&2 | |
| exit 1 | |
| fi | |
| if [[ ! -f "$RAG_PATH" ]]; then | |
| echo "❌ rag chunks file not found at $RAG_PATH" >&2 | |
| exit 1 | |
| fi | |
| if [[ ! -f "$PROMPT_FILE" ]]; then | |
| echo "❌ generator prompt not found at $PROMPT_FILE" >&2 | |
| exit 1 | |
| fi | |
| NODE_OUTPUT="$(CHUNK_ID="$CHUNK_ID" QUESTION_INDEX="$QUESTION_INDEX" QUESTIONS_FILE="$QUESTIONS_FILE" RAG_PATH="$RAG_PATH" RANDOM_MODE="$RANDOM_MODE" node --input-type=module <<'NODE' | |
| import fs from 'fs'; | |
| import crypto from 'crypto'; | |
| const chunkIdArg = process.env.CHUNK_ID || ''; | |
| const qIndex = Number(process.env.QUESTION_INDEX || '0'); | |
| const questionsFile = process.env.QUESTIONS_FILE; | |
| const ragPath = process.env.RAG_PATH; | |
| const randomMode = process.env.RANDOM_MODE === '1'; | |
| function normalizeText(text = '') { | |
| return String(text).replace(/\s+/g, ' ').trim(); | |
| } | |
| function chunkIdFromContent(content, sourceId) { | |
| const base = normalizeText(content); | |
| return crypto.createHash('sha256').update(`${base}|${sourceId ?? ''}`).digest('hex'); | |
| } | |
| function fail(msg) { | |
| console.error(msg); | |
| process.exit(2); | |
| } | |
| const questionLines = fs.readFileSync(questionsFile, 'utf8') | |
| .split('\n') | |
| .map((l) => l.trim()) | |
| .filter(Boolean); | |
| const records = questionLines.map((l) => { | |
| try { | |
| return JSON.parse(l); | |
| } catch { | |
| return null; | |
| } | |
| }).filter(Boolean); | |
| if (records.length === 0) fail('No cached questions found.'); | |
| const ragLines = fs.readFileSync(ragPath, 'utf8') | |
| .split('\n') | |
| .map((l) => l.trim()) | |
| .filter(Boolean); | |
| const ragMap = new Map(); | |
| ragLines.forEach((line, idx) => { | |
| let obj; | |
| try { | |
| obj = JSON.parse(line); | |
| } catch { | |
| return; | |
| } | |
| const content = | |
| obj.content || | |
| obj.text || | |
| obj.chunk || | |
| obj.body || | |
| ''; | |
| const sourceId = | |
| obj.id || | |
| obj.session_key || | |
| obj.title || | |
| `jsonl-${idx}`; | |
| const cid = chunkIdFromContent(content, sourceId); | |
| ragMap.set(cid, { content, sourceId, source: obj }); | |
| }); | |
| const matchingRecords = records.filter((r) => ragMap.has(r.chunk_id)); | |
| let record = null; | |
| if (chunkIdArg) { | |
| record = records.find((r) => r.chunk_id === chunkIdArg); | |
| if (!record) fail(`Chunk ${chunkIdArg} not found in questions cache.`); | |
| if (!ragMap.has(record.chunk_id)) { | |
| fail(`Chunk content for ${record.chunk_id} not found in ${ragPath}.`); | |
| } | |
| } else if (randomMode) { | |
| if (matchingRecords.length === 0) { | |
| fail('No cached chunk IDs match rag chunks. Run the pipeline to populate cache.'); | |
| } | |
| record = matchingRecords[crypto.randomInt(matchingRecords.length)]; | |
| } else { | |
| record = matchingRecords[0]; | |
| if (!record) { | |
| fail('No cached chunk IDs match rag chunks. Run the pipeline to populate cache.'); | |
| } | |
| } | |
| const questions = record.questions || []; | |
| let chosenQIndex = qIndex; | |
| if (randomMode) { | |
| chosenQIndex = questions.length > 0 ? crypto.randomInt(questions.length) : 0; | |
| } | |
| const question = questions?.[chosenQIndex]; | |
| if (!question) fail(`Question index ${qIndex} out of range for chunk ${record.chunk_id}.`); | |
| const matchedChunk = ragMap.get(record.chunk_id); | |
| console.log(JSON.stringify({ | |
| chunkId: record.chunk_id, | |
| question, | |
| questionIndex: chosenQIndex, | |
| chunk: matchedChunk.content, | |
| source: matchedChunk.source, | |
| })); | |
| NODE | |
| )" | |
| CHUNK_ID_RESOLVED="$(echo "$NODE_OUTPUT" | jq -r '.chunkId')" | |
| QUESTION="$(echo "$NODE_OUTPUT" | jq -r '.question')" | |
| CHUNK="$(echo "$NODE_OUTPUT" | jq -r '.chunk')" | |
| QUESTION_INDEX="$(echo "$NODE_OUTPUT" | jq -r '.questionIndex')" | |
| echo "🧩 Chunk: $CHUNK_ID_RESOLVED" | |
| echo " Question [$QUESTION_INDEX]: $QUESTION" | |
| echo " Model: $MODEL" | |
| echo " Prompt file: $PROMPT_FILE" | |
| echo "----------------------------------------------" | |
| echo "$CHUNK" | head -n 20 | |
| echo "… (chunk truncated)" | |
| echo "----------------------------------------------" | |
| PROMPT="$(QUESTION="$QUESTION" CHUNK="$CHUNK" PROMPT_FILE="$PROMPT_FILE" node --input-type=module <<'NODE' | |
| import fs from 'fs'; | |
| const tpl = fs.readFileSync(process.env.PROMPT_FILE, 'utf8'); | |
| const question = process.env.QUESTION; | |
| const context = process.env.CHUNK; | |
| const out = tpl | |
| .split('{{QUESTION}}').join(question) | |
| .split('{{CONTEXT}}').join(context); | |
| process.stdout.write(out); | |
| NODE | |
| )" | |
| PROMPT_JSON=$(printf '%s' "$PROMPT" | jq -Rs .) | |
| if [[ "$REASONING" == "1" ]]; then | |
| echo "🧠 Reasoning: ON" | |
| OPTIONS='"options":{"reasoning":true},' | |
| else | |
| OPTIONS="" | |
| fi | |
| PAYLOAD=$(cat <<EOF | |
| { | |
| "model": "$MODEL", | |
| "prompt": $PROMPT_JSON, | |
| $OPTIONS | |
| "stream": false | |
| } | |
| EOF | |
| ) | |
| echo | |
| echo "🚀 Sending to Ollama ($MODEL)…" | |
| echo | |
| RAW_RESPONSE=$(mktemp) | |
| curl -s -X POST "$OLLAMA_URL/api/generate" \ | |
| -H "Content-Type: application/json" \ | |
| -d "$PAYLOAD" | tee "$RAW_RESPONSE" \ | |
| | jq 'del(.context)' | |
| echo | |
| echo "📝 Response text:" | |
| jq -r '.response // .message // .output' "$RAW_RESPONSE" | |