Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions docs/PRODUCT_READINESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,8 @@
char-based 近似模型。
- [ ] 🟡 **C-2 單價對齊真實**(GATE,需查官方定價)— 現況單價是估算。對齊 Gemini 3 系列 +
GCP TTS + (未來)image 真實單價。定價會變動 → 抽成設定常數 + 文件註明「以官方為準」。
- [~] 🟡 **C-3 旁白模型遷 3.x**(GATE,需開額度驗證品質)— `slide_ingest.py:43`
`MODEL = "gemini-2.5-flash"`(將淘汰)。**M 軸完成後這只是改角色表 `text.fast` 一個值**。
- [x] 🟡 **C-3 旁白模型遷 3.x**(GATE→已驗已切)— ✅ 2026-06-15 完成。`slide_ingest.py`
原寫死 `MODEL = "gemini-2.5-flash"`(將淘汰)。**M 軸完成後切換只是改角色表 `text.fast` 一個值**。
3.5-flash 實測接受 `thinking_budget=0`,但**旁白品質要先驗**再換。寫成 A/B proposal,劉老師
開額度跑過再切。(劉老師 2026-06-07:需額度會給權限;2026-06-15:開額度。)
- ✅ 2026-06-15 **A/B 工具 + 提案完成(offline 前置;實跑=你本機開額度)**。劉老師 2026-06-15
Expand All @@ -283,8 +283,18 @@
(chokepoint 改走 `resolve("text.fast")`)+ rollback(設定頁覆寫回 2.5、免改 code)/ 3 個待拍板
開放問題(範圍 / `text.fast` vs 新增 `narration` 角色 / 候選模型)。補 `tests/test_ab_narration.py`
11 測(頁碼解析 / run_ab 每頁每模型透傳 / 報告並排+用量 / 缺 key SystemExit,**全 fake client
不打 API**)。本機相關子集 142 passed。**下一步=你本機跑 A/B → 看品質 → 回報要不要切**,要切就
開後續一刀換 chokepoint。
不打 API**)。本機相關子集 142 passed。
- ✅ 2026-06-15 **切換完成(劉老師本機 A/B 驗過品質後拍板遷移)**。劉老師跑 A/B(材力/自控
`Chap08-PID控制器設計` 三頁)逐項比對:**正確性兩邊都乾淨無誤**(review gate 真正守的底線)、
3.5-flash **口吻更自然 + 長度更貼 ~75s/頁時間預算**(2.5 偏長易被 `_truncate_at_sentence` 截)、
**成本約 64%**(省 ~36% 輸出字);唯一退步是 3.5 偶爾壓縮會漏列點(學習目標頁少帶一項)。
拍板**切**。落地:`slide_ingest.py` 把寫死 `MODEL` 換成 `narration_model()=resolve_id(TEXT_FAST)`
(**呼叫時解析**=設定頁 `text.fast` 覆寫即時生效),**旁白 + 章節切分**一起遷(共用同一模型常數,
章節切分也得離開 2.5);並在 `NARRATION_PROMPT_DETAILED` 補第 7 條「條列項目每項至少帶一句、可
精簡不可整項遺漏」糾正 3.5 唯一弱點。**rollback 免改 code**:設定頁把 `text.fast` 覆寫回
`gemini-2.5-flash` 即時退。**`solve.py`(解題)模型不在本遷移範圍**(正確性更敏感、未 A/B,另議)。
`model` 計帳如實落 resolved id。本機全套 2702 passed(剩 1 QR 像素為容器缺 Noto CJK 字型假象,
CI 權威)。至此「換旁白模型 = 改登錄表/設定頁 `text.fast` 一個值」閉環。
- [ ] 🟢 **C-4 `gemini-3.1-pro-image` 等開放再換**(GATE)— 劉老師想用但 API 未開放。等開放
從 `gemini-3-pro-image` 換(`core/infocards/models.py`)。掛追蹤。
- [x] 🟢 **C-5 模型 id 自我健檢**(offline)— ✅ 2026-06-09 完成。新增 `tools/check_models.py`:蒐集
Expand Down
25 changes: 18 additions & 7 deletions slide_ingest.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,16 @@
SLIDES_ROOT = BASE_DIR / "slides"
EXAMS_ROOT = BASE_DIR / "exams"

MODEL = "gemini-2.5-flash"
# C-3(2026-06-15 劉老師拍板,A/B 驗過品質後遷移):旁白 + 章節切分模型走 M 軸角色登錄表
# text.fast(預設 gemini-3.5-flash),不再寫死 gemini-2.5-flash(將淘汰)。換模型=改登錄表/
# 設定頁 text.fast 一個值;rollback 把 text.fast 覆寫回 2.5 即可、免改 code。呼叫時解析 →
# 設定頁覆寫即時生效。注意:solve.py(解題)模型不在此遷移範圍(正確性更敏感、未 A/B)。
def narration_model() -> str:
"""旁白 / 章節切分用的模型 id(M 軸 text.fast 角色,呼叫時解析)。"""
from core.models import TEXT_FAST, resolve_id
return resolve_id(TEXT_FAST)


# Gemini HTTP 逾時 (毫秒): 不設的話連線 stall 會無限掛住 (140 頁論文出過此狀況)。
GEMINI_TIMEOUT_MS = 90_000
SLIDE_DPI = 200 # 1920px 寬左右 (16:9 投影片)
Expand Down Expand Up @@ -100,6 +109,7 @@
4. 開頭銜接多樣化, 不要每張都「好, 我們來看」
5. 不要 LaTeX、不要 Markdown、不要符號標記; 程式碼用「等於」「冒號」念
6. 純中文 + 必要英文術語 / 數值
7. 若投影片以條列列出多個項目/目標/步驟, 每一項都要至少帶到一句, 可精簡但不要整項遺漏

==== 輸出格式 ====
直接輸出純文字, 不要前言、引號、分段。
Expand Down Expand Up @@ -176,19 +186,20 @@ def detect_chapters_with_gemini(thumbs: list[bytes], total_pages: int) -> list[d
client = genai.Client(api_key=api_key,
http_options=types.HttpOptions(timeout=GEMINI_TIMEOUT_MS))

model = narration_model()
parts = [types.Part.from_bytes(data=t, mime_type="image/png") for t in thumbs]
resp = client.models.generate_content(
model=MODEL,
model=model,
contents=parts + [CHAPTER_PROMPT],
# thinking_budget=0: 2.5-flash 預設開 thinking, 會吃掉 max_output_tokens 導致回空/截斷,
# thinking_budget=0: flash 系列預設開 thinking, 會吃掉 max_output_tokens 導致回空/截斷,
# 且每次呼叫慢 5 倍 (11s→2s)。章節切分/旁白都不需要 thinking。
config=types.GenerateContentConfig(
temperature=0.1, max_output_tokens=4096,
thinking_config=types.ThinkingConfig(thinking_budget=0)),
)
raw = (resp.text or "").strip()
from core import usage
usage.record_text_now("video", MODEL, CHAPTER_PROMPT, raw, label="chapters")
usage.record_text_now("video", model, CHAPTER_PROMPT, raw, label="chapters")
if "```" in raw:
raw = raw.split("```")[1]
if raw.startswith("json"):
Expand Down Expand Up @@ -272,11 +283,11 @@ def narrate_page_with_gemini(client, page_png: bytes, chapter_title: str,
"""單頁 → narration 草稿。Gemini 偶爾會在中文句中提早 STOP 導致句子腰斬,
結尾若不是句號類符號就 retry 一次, temperature 提高 + prompt 加強完整性要求。

model: 覆寫旁白模型 id(預設沿用模組 MODEL)。供 C-3 旁白模型 A/B 比對用
(tools/ab_narration.py 對同一頁跑 2.5 vs 3.x 比品質),不影響正式 pipeline 預設。"""
model: 覆寫旁白模型 id(預設走角色登錄表 text.fast=narration_model())。供 C-3 旁白模型
A/B 比對用(tools/ab_narration.py 對同一頁跑 2.5 vs 3.x 比品質)。"""
from google.genai import types

model = model or MODEL
model = model or narration_model()

template = NARRATION_PROMPT_BRIEF if brief else NARRATION_PROMPT_DETAILED
base_prompt = template.format(
Expand Down
Loading