Luigi commited on
Commit
f03d62b
·
1 Parent(s): 25e4563

fix: loosen schema validation and add examples to extraction prompts

Browse files

- Loosened JSON schema validation to accept partial results
- Fill missing keys with empty arrays instead of failing
- Convert string values to single-item arrays
- Added concrete extraction examples to prompts
- Shows what good extractions look like for this specific content
- Includes DDR4 shortage, AI demand, Samsung allocation examples
- Improved instructions to emphasize JSON validity

This should address systematic extraction failures by:
1. Not rejecting partial valid output
2. Giving models clear examples of expected format

Files changed (1) hide show
  1. meeting_summarizer/extraction.py +71 -43
meeting_summarizer/extraction.py CHANGED
@@ -664,15 +664,21 @@ def _try_parse_extraction_json(
664
  else:
665
  return None
666
 
667
- # Validate schema
668
  required_keys = {"action_items", "decisions", "key_points", "open_questions"}
669
- if not isinstance(data, dict) or not required_keys.issubset(data.keys()):
670
  return None
671
 
672
- # Validate all values are lists
673
  for key in required_keys:
674
- if not isinstance(data[key], list):
675
- return None
 
 
 
 
 
 
676
 
677
  # Normalize items (flatten dicts to strings)
678
  return _normalize_extraction_items(data)
@@ -690,21 +696,35 @@ def _sample_llm_response(text: str, max_chars: int = 400) -> str:
690
  def _build_schema_extraction_prompt(output_language: str) -> str:
691
  """Build concise schema-based extraction prompt (optimized for non-reasoning models)."""
692
  if output_language == "zh-TW":
693
- return """以 JSON 格式返回資料,使用以下架構:
694
-
 
695
  {
696
- "action_items": ["具體行動項目1"],
697
- "decisions": ["決策1"],
698
- "key_points": ["要點1"],
699
- "open_questions": ["問題1"]
700
  }
701
-
702
- action_items: 包含負責人和截止日期具體行動項目
703
- decisions: 包合理由的決策
704
- key_points: 重要討論要點
705
- open_questions: 未解的問題或疑慮
706
-
707
- 從使用者提供的逐字稿中提取。逐字稿可能包含重複、雜訊或不完整內容,請專注於有意義的對話內容,忽略重複的詞句。"""
 
 
 
 
 
 
 
 
 
 
 
 
 
708
  else:
709
  return """Return data as a JSON object with the following schema:
710
 
@@ -726,35 +746,43 @@ def _build_schema_extraction_prompt(output_language: str) -> str:
726
  def _build_reasoning_extraction_prompt(output_language: str) -> str:
727
  """Build verbose extraction prompt with reasoning instructions (for hybrid models like Qwen3)."""
728
  if output_language == "zh-TW":
729
- return """你是會議分析助手。
730
-
731
- 使用你的推理能力分析內容後再進行提取。
732
-
733
- 你的推理應該
734
- 1. 識別關鍵決策點和行動項目
735
- 2. 區分明確決策與一般討論
736
- 3. 適當分類資訊(行動 vs 要點 vs 問題
737
-
738
- 逐字稿可能包含重複、雜訊或不完整內容,請專注於有意義的對話內容,忽略重複的詞句。
739
-
740
- 推理後,以 JSON 格式返回資料,使用以下架構:
741
  {
742
- "action_items": ["具體行動項目1", "具體行動項目2"],
 
 
 
 
 
 
 
 
743
  "decisions": ["決策1", "決策2"],
744
- "key_points": ["要點1", "要點2"],
745
  "open_questions": ["問題1", "問題2"]
746
  }
747
-
748
- action_items: 包含負責人和截止日期的具體行動項目
749
- decisions: 包合理由的決策
750
- key_points: 重要討論要點
751
- open_questions: 未解決的問題或疑慮
752
-
753
- 規則:
754
- - 每個項目必須是完整、獨立的句子
755
- - 在每個項目中包含上下文(誰、什麼、何時)
756
- - 如果類別沒有項目,使用空陣列 []
757
- - 僅輸出 JSON,無 markdown,無解釋"""
 
 
758
  else:
759
  return """You are a meeting analysis assistant.
760
 
 
664
  else:
665
  return None
666
 
667
+ # Validate schema - be lenient and fill missing keys
668
  required_keys = {"action_items", "decisions", "key_points", "open_questions"}
669
+ if not isinstance(data, dict):
670
  return None
671
 
672
+ # Fill missing keys with empty arrays (allow partial extraction)
673
  for key in required_keys:
674
+ if key not in data:
675
+ data[key] = []
676
+ elif not isinstance(data[key], list):
677
+ # If value exists but isn't a list, try to convert or use empty
678
+ if isinstance(data[key], str):
679
+ data[key] = [data[key]]
680
+ else:
681
+ data[key] = []
682
 
683
  # Normalize items (flatten dicts to strings)
684
  return _normalize_extraction_items(data)
 
696
  def _build_schema_extraction_prompt(output_language: str) -> str:
697
  """Build concise schema-based extraction prompt (optimized for non-reasoning models)."""
698
  if output_language == "zh-TW":
699
+ return """從會議逐字稿中提取關鍵資訊,以 JSON 格式返回
700
+
701
+ 範例輸出 (Example):
702
  {
703
+ "action_items": ["與三星討論Q3產能分配", "確認LPDDR4供應數量"],
704
+ "decisions": ["優先供應大客戶浪潮", "暫停接受新訂單"],
705
+ "key_points": ["DDR4缺貨持續到2028年", "AI需求占全球產能45%", "美光可能跟進SanDisk付款條件"],
706
+ "open_questions": ["Q2價格漲幅預估", "深圳測試場良率確認"]
707
  }
708
+
709
+ 使用以下架構,必須返回有效 JSON:
710
+ {
711
+ "action_items": ["具體行動項目1", "具體行動項目2"],
712
+ "decisions": ["策1", "決策2"],
713
+ "key_points": ["要點1", "要點2", "要點3"],
714
+ "open_questions": ["問題1", "問題2"]
715
+ }
716
+
717
+ 說明:
718
+ - action_items: 具體行動項目(包含負責人、時間、內容)
719
+ - decisions: 已做出的決策(包合理由)
720
+ - key_points: 重要討論要點(市場趨勢、供應狀況、策略調整)
721
+ - open_questions: 未解決的問題或疑慮
722
+
723
+ 規則:
724
+ 1. 必須返回有效的 JSON 格式
725
+ 2. 每個類別至少提取1-3個項目,如果沒有則返回空陣列 []
726
+ 3. 項目必須是具體的句子,不是關鍵詞
727
+ 4. 專注於商業決策和行動,忽略重複詞句"""
728
  else:
729
  return """Return data as a JSON object with the following schema:
730
 
 
746
  def _build_reasoning_extraction_prompt(output_language: str) -> str:
747
  """Build verbose extraction prompt with reasoning instructions (for hybrid models like Qwen3)."""
748
  if output_language == "zh-TW":
749
+ return """你是會議分析助手。分析會議逐字稿並提取關鍵資訊。
750
+
751
+ 分析步驟:
752
+ 1. 先理解對話內容:討論了什麼主題?涉及哪些公司/產品?
753
+ 2. 識別決策點有哪些明確的決定或策略調整?
754
+ 3. 找出行動項目:需要執行的具體任務
755
+ 4. 記錄重要資訊:市場趨勢、供應狀況、價格變化
756
+ 5. 標記未解決問題:還不清楚或需要後續確認的事項
757
+
758
+ 範例輸出:
 
 
759
  {
760
+ "action_items": ["與三星討論Q3產能分配", "確認LPDDR4供應數量"],
761
+ "decisions": ["優先供應大客戶浪潮", "暫停接受新訂單"],
762
+ "key_points": ["DDR4缺貨持續到2028年", "AI需求占全球產能45%", "美光可能跟進SanDisk付款條件"],
763
+ "open_questions": ["Q2價格漲幅預估", "深圳測試場良率確認"]
764
+ }
765
+
766
+ 返回格式(必須是有效的 JSON):
767
+ {
768
+ "action_items": ["行動項目1", "行動項目2"],
769
  "decisions": ["決策1", "決策2"],
770
+ "key_points": ["要點1", "要點2", "要點3"],
771
  "open_questions": ["問題1", "問題2"]
772
  }
773
+
774
+ 說明:
775
+ - action_items: 具體行動項目(誰要做什麼、何時完成)
776
+ - decisions: 已做出的決策(包合理由)
777
+ - key_points: 重要討論要點(市場趨勢、供應狀況、策略)
778
+ - open_questions: 未解決的問題或疑慮
779
+
780
+ 規則:
781
+ 1. 必須返回有效的 JSON 格式
782
+ 2. 每個類別提取1-5個項目,如果沒有則返回空陣列 []
783
+ 3. 項目必須是具體的完整句子
784
+ 4. 專注於商業決策和行動,忽略重複詞句和閒聊
785
+ 5. 僅輸出 JSON,不要推理過程"""
786
  else:
787
  return """You are a meeting analysis assistant.
788