Spaces:
Running
Running
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
- 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)
|
| 670 |
return None
|
| 671 |
|
| 672 |
-
#
|
| 673 |
for key in required_keys:
|
| 674 |
-
if not
|
| 675 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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": ["
|
| 697 |
-
"decisions": ["
|
| 698 |
-
"key_points": ["
|
| 699 |
-
"open_questions": ["
|
| 700 |
}
|
| 701 |
-
|
| 702 |
-
|
| 703 |
-
|
| 704 |
-
|
| 705 |
-
|
| 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 |
-
|
| 735 |
-
|
| 736 |
-
|
| 737 |
-
|
| 738 |
-
|
| 739 |
-
|
| 740 |
-
推理後,以 JSON 格式返回資料,使用以下架構:
|
| 741 |
{
|
| 742 |
-
"action_items": ["
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 743 |
"decisions": ["決策1", "決策2"],
|
| 744 |
-
"key_points": ["要點1", "要點2"],
|
| 745 |
"open_questions": ["問題1", "問題2"]
|
| 746 |
}
|
| 747 |
-
|
| 748 |
-
|
| 749 |
-
|
| 750 |
-
|
| 751 |
-
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
|
| 755 |
-
|
| 756 |
-
|
| 757 |
-
|
|
|
|
|
|
|
| 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 |
|