Files
python-template/backend/example_gemini_usage.py
brunoandClaude 15b2471c2f feat: 集成 Google Gemini 3 Pro 模型并修复 JSON 转义问题
## 主要改进

### 🚀 Gemini 3 Pro 集成
- 支持通过 OpenRouter API 调用 Google Gemini 3 Pro Preview 模型
- 针对数学试卷优化 prompt,增强数学公式识别能力
- 自动检测 Gemini 模型并启用数学优化模式
- 设置 Gemini 3 Pro 为默认解析模型(AI_MODEL 环境变量)

### 🔧 JSON 转义修复
- 实现 fix_json_escaping() 函数处理 LaTeX 公式中的反斜杠
- 智能识别并转义 LaTeX 命令(\frac, \sqrt, \pm 等)
- 保留有效的 JSON 转义序列(\", \\, \/, \uXXXX)
- 解决 Gemini 返回的 LaTeX 公式 JSON 解析失败问题

### 📐 数学解析增强
- 详细的 LaTeX 公式转换说明(分数、根式、积分、矩阵等)
- 特殊数学符号支持(不等式、集合、逻辑、箭头等)
- 几何图形识别和描述
- 完整的解题步骤和思路分析

### 📝 新增文件
- GEMINI_INTEGRATION.md: 完整的集成文档
- test_gemini_math.py: Claude vs Gemini 对比测试脚本
- test_gemini_fixed.py: JSON 修复验证测试
- example_gemini_usage.py: 使用示例和最佳实践
- quick_test_gemini.sh: 快速测试脚本

### 🎯 测试结果
- ✅ 成功解析数学试卷(5 道题,100 分)
- ✅ 正确提取所有 LaTeX 公式
- ✅ 详细的解题步骤和知识点标注
- ✅ 准确的难度评估(难度 2-5)

## 配置说明

在 .env 文件中设置:
```bash
AI_MODEL=google/gemini-3-pro-preview
USE_CLAUDE_PARSER=true
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
2025-11-22 22:44:37 +08:00

264 lines
8.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Gemini 3 Pro 数学试卷解析示例
展示如何使用 Gemini 模型进行数学试卷解析
"""
import os
import json
from dotenv import load_dotenv
from claude_exam_parser import ClaudeExamParser
# 加载环境变量
load_dotenv()
def example_1_basic_usage():
"""示例1: 基本使用 - 使用 Gemini 解析数学试卷"""
print("=" * 80)
print("示例1: 使用 Gemini 3 Pro 解析数学试卷")
print("=" * 80)
# 创建解析器,明确指定使用 Gemini 模型
parser = ClaudeExamParser(
model="google/gemini-3-pro-preview"
)
# 解析数学试卷
# 注意:请替换为实际的试卷文件路径
result = parser.parse_exam_file(
file_path="sample_math_exam.pdf", # 替换为实际文件
subject="数学",
grade="高一"
)
if result["success"]:
data = result["result"]
print(f"\n✅ 解析成功!")
print(f"学科: {data['subject']}")
print(f"年级: {data.get('grade', 'N/A')}")
print(f"题目总数: {data['total_questions']}")
print(f"\n前3道题目:")
for q in data["questions"][:3]:
print(f"\n 题目 {q['number']} ({q['type']})")
print(f" 题干: {q['question'][:100]}...")
if q.get("formulas"):
print(f" 公式: {q['formulas'][:2]}")
print(f" 难度: {q.get('difficulty', 'N/A')}")
else:
print(f"\n❌ 解析失败: {result['error']}")
def example_2_compare_models():
"""示例2: 对比不同模型的解析效果"""
print("\n\n" + "=" * 80)
print("示例2: 对比 Claude 和 Gemini 的解析效果")
print("=" * 80)
file_path = "sample_math_exam.pdf" # 替换为实际文件
models = [
"anthropic/claude-sonnet-4.5",
"google/gemini-3-pro-preview"
]
results = {}
for model in models:
print(f"\n正在使用 {model} 解析...")
parser = ClaudeExamParser(model=model)
result = parser.parse_exam_file(file_path, subject="数学")
if result["success"]:
data = result["result"]
# 统计公式数量
formula_count = sum(
len(q.get("formulas", []))
for q in data.get("questions", [])
)
results[model] = {
"total_questions": data.get("total_questions", 0),
"formula_count": formula_count
}
print(f" ✅ 识别题目: {results[model]['total_questions']}")
print(f" ✅ 提取公式: {results[model]['formula_count']}")
else:
print(f" ❌ 解析失败: {result['error']}")
print(f"\n对比结果:")
print(json.dumps(results, indent=2, ensure_ascii=False))
def example_3_extract_formulas():
"""示例3: 提取并分析数学公式"""
print("\n\n" + "=" * 80)
print("示例3: 提取并分析数学公式")
print("=" * 80)
parser = ClaudeExamParser(model="google/gemini-3-pro-preview")
result = parser.parse_exam_file(
file_path="sample_math_exam.pdf", # 替换为实际文件
subject="数学"
)
if result["success"]:
data = result["result"]
all_formulas = []
# 收集所有公式
for q in data["questions"]:
formulas = q.get("formulas", [])
if formulas:
all_formulas.extend([
{
"question_number": q["number"],
"formula": f
}
for f in formulas
])
print(f"\n找到 {len(all_formulas)} 个公式:")
for i, item in enumerate(all_formulas[:10], 1): # 显示前10个
print(f"{i}. 题目 {item['question_number']}: {item['formula']}")
# 分析公式类型
formula_types = {
"分数": 0,
"根式": 0,
"积分": 0,
"求和": 0,
"向量": 0
}
for item in all_formulas:
formula = item["formula"]
if "\\frac" in formula:
formula_types["分数"] += 1
if "\\sqrt" in formula:
formula_types["根式"] += 1
if "\\int" in formula:
formula_types["积分"] += 1
if "\\sum" in formula:
formula_types["求和"] += 1
if "\\vec" in formula or "\\overrightarrow" in formula:
formula_types["向量"] += 1
print(f"\n公式类型分布:")
for ftype, count in formula_types.items():
if count > 0:
print(f" {ftype}: {count}")
def example_4_analyze_difficulty():
"""示例4: 分析题目难度分布"""
print("\n\n" + "=" * 80)
print("示例4: 分析题目难度分布")
print("=" * 80)
parser = ClaudeExamParser(model="google/gemini-3-pro-preview")
result = parser.parse_exam_file(
file_path="sample_math_exam.pdf", # 替换为实际文件
subject="数学"
)
if result["success"]:
data = result["result"]
# 难度分布
difficulty_dist = data.get("stats", {}).get("difficulty_distribution", {})
if difficulty_dist:
print(f"\n难度分布:")
total = sum(difficulty_dist.values())
for level in sorted(difficulty_dist.keys()):
count = difficulty_dist[level]
percentage = (count / total) * 100
bar = "█" * int(percentage / 5)
print(f" 难度 {level}: {count:2d} 题 ({percentage:5.1f}%) {bar}")
# 按难度分组题目
by_difficulty = {}
for q in data["questions"]:
diff = q.get("difficulty", 0)
if diff not in by_difficulty:
by_difficulty[diff] = []
by_difficulty[diff].append(q["number"])
print(f"\n各难度题目编号:")
for level in sorted(by_difficulty.keys()):
questions = by_difficulty[level]
print(f" 难度 {level}: {', '.join(map(str, questions))}")
def example_5_knowledge_points():
"""示例5: 分析知识点覆盖"""
print("\n\n" + "=" * 80)
print("示例5: 分析知识点覆盖")
print("=" * 80)
parser = ClaudeExamParser(model="google/gemini-3-pro-preview")
result = parser.parse_exam_file(
file_path="sample_math_exam.pdf", # 替换为实际文件
subject="数学"
)
if result["success"]:
data = result["result"]
# 统计知识点
knowledge_point_count = {}
for q in data["questions"]:
points = q.get("knowledge_points", [])
for point in points:
knowledge_point_count[point] = knowledge_point_count.get(point, 0) + 1
# 按出现频率排序
sorted_points = sorted(
knowledge_point_count.items(),
key=lambda x: x[1],
reverse=True
)
print(f"\n知识点覆盖 (共 {len(sorted_points)} 个知识点):")
for point, count in sorted_points[:15]: # 显示前15个
bar = "●" * count
print(f" {point:20s}: {count:2d} 题 {bar}")
def main():
"""主函数 - 运行所有示例"""
print("\n")
print("╔" + "=" * 78 + "╗")
print("║" + " " * 20 + "Gemini 3 Pro 数学试卷解析示例" + " " * 28 + "║")
print("╚" + "=" * 78 + "╝")
# 检查 API Key
if not os.getenv("OPENROUTER_API_KEY"):
print("\n❌ 错误: 未设置 OPENROUTER_API_KEY")
print("请在 .env 文件中设置,或运行: export OPENROUTER_API_KEY='your-key'")
return
# 运行示例(注意:需要实际的PDF文件)
print("\n⚠️ 注意: 这些示例需要实际的PDF试卷文件")
print("请将 'sample_math_exam.pdf' 替换为实际的文件路径\n")
# 可以取消注释运行各个示例
# example_1_basic_usage()
# example_2_compare_models()
# example_3_extract_formulas()
# example_4_analyze_difficulty()
# example_5_knowledge_points()
print("\n使用说明:")
print("1. 准备一份数学试卷 PDF 文件")
print("2. 编辑此文件,将 'sample_math_exam.pdf' 替换为实际文件路径")
print("3. 取消注释要运行的示例")
print("4. 运行: python example_gemini_usage.py")
print("\n或者直接使用测试脚本:")
print(" ./quick_test_gemini.sh your_math_exam.pdf 数学 高一")
if __name__ == "__main__":
main()