131 lines
4.1 KiB
Python
131 lines
4.1 KiB
Python
|
import logging
|
|||
|
from openai import OpenAI
|
|||
|
from Config.Config import ALY_LLM_API_KEY, ALY_LLM_MODEL_NAME, ALY_LLM_BASE_URL
|
|||
|
logger = logging.getLogger(__name__)
|
|||
|
|
|||
|
|
|||
|
# 生成GeoGebra命令
|
|||
|
def generate_ggb(ocr_result, qvq_result, output_dir):
|
|||
|
# 初始化OpenAI客户端
|
|||
|
client = OpenAI(
|
|||
|
api_key=ALY_LLM_API_KEY,
|
|||
|
base_url=ALY_LLM_BASE_URL
|
|||
|
)
|
|||
|
|
|||
|
reasoning_content = "" # 定义完整思考过程
|
|||
|
answer_content = "" # 定义完整回复
|
|||
|
is_answering = False # 判断是否结束思考过程并开始回复
|
|||
|
|
|||
|
prompt = """
|
|||
|
几何试题转GeoGebra命令生成提示词(可行版)
|
|||
|
|
|||
|
输入数据
|
|||
|
1. 文本条件(OCR提取结果)
|
|||
|
2. 图形结构(图像识别JSON)
|
|||
|
|
|||
|
核心处理规则
|
|||
|
1. 必须建立基础坐标系:
|
|||
|
- 明确指定原点(0,0)
|
|||
|
- 明确指定x轴方向
|
|||
|
|
|||
|
2. 点创建原则:
|
|||
|
a) 根据视觉提供的信息进行大致位置估算
|
|||
|
b) 禁止创建无约束的自由点
|
|||
|
|
|||
|
3. 线段创建:
|
|||
|
- 如果题目与图形中没有明确的长度声明,可以视最长边长度为10个单位,其它边以此为基础计算长度。
|
|||
|
- 没有明显提出是动点的,不要使用滑块,可以依据题意估算即可。
|
|||
|
- 只连接已定义的点
|
|||
|
- 禁止创建未定义端点的线段
|
|||
|
|
|||
|
4. 几何关系实现:
|
|||
|
- 垂直关系:使用PerpendicularLine命令
|
|||
|
- 中点关系:使用Midpoint命令
|
|||
|
|
|||
|
5. 严格构建顺序:
|
|||
|
1) 创建坐标系基准点
|
|||
|
2) 创建其他点
|
|||
|
3) 创建线段
|
|||
|
4) 创建多边形
|
|||
|
|
|||
|
冲突处理
|
|||
|
1. 图文冲突:优先文本条件
|
|||
|
2. 信息缺失:使用最小可行假设
|
|||
|
- 假设直角在原点
|
|||
|
- 假设单位长度
|
|||
|
|
|||
|
禁止输出
|
|||
|
1. Point()无参数命令
|
|||
|
2. 未定义端点的线段
|
|||
|
3. 无法实现的注释关系
|
|||
|
4. 未连接点的多边形
|
|||
|
5. Geogebra指令集中的注释
|
|||
|
6. PerpendicularLine
|
|||
|
|
|||
|
特殊情形处理
|
|||
|
1. 中点:Midpoint命令
|
|||
|
2. 动点:Slider
|
|||
|
3. 几何问题一般避免使用射线,优先使用线段
|
|||
|
|
|||
|
|
|||
|
### 题目的文字描述信息
|
|||
|
```
|
|||
|
{Ocr}
|
|||
|
```
|
|||
|
|
|||
|
### 题目的图形描述信息
|
|||
|
```
|
|||
|
{Qvq}
|
|||
|
```
|
|||
|
"""
|
|||
|
|
|||
|
with open(ocr_result, 'r', encoding='utf-8') as file:
|
|||
|
Ocr = file.read() # 直接获取整个文件内容为字符串
|
|||
|
|
|||
|
with open(qvq_result, 'r', encoding='utf-8') as file:
|
|||
|
Qvq = file.read() # 直接获取整个文件内容为字符串
|
|||
|
|
|||
|
prompt = prompt.replace("{Qvq}", Qvq)
|
|||
|
prompt = prompt.replace("{Ocr}", Ocr)
|
|||
|
# 创建聊天完成请求
|
|||
|
completion = client.chat.completions.create(
|
|||
|
model=ALY_LLM_MODEL_NAME,
|
|||
|
messages=[
|
|||
|
{
|
|||
|
"role": "user",
|
|||
|
"content": [
|
|||
|
{"type": "text",
|
|||
|
"text": prompt},
|
|||
|
],
|
|||
|
},
|
|||
|
],
|
|||
|
stream=True,
|
|||
|
)
|
|||
|
|
|||
|
print("\n" + "=" * 20 + "思考过程" + "=" * 20 + "\n")
|
|||
|
|
|||
|
for chunk in completion:
|
|||
|
# 如果chunk.choices为空,则打印usage
|
|||
|
if not chunk.choices:
|
|||
|
print("\nUsage:")
|
|||
|
print(chunk.usage)
|
|||
|
else:
|
|||
|
delta = chunk.choices[0].delta
|
|||
|
# 打印思考过程
|
|||
|
if hasattr(delta, 'reasoning_content') and delta.reasoning_content != None:
|
|||
|
print(delta.reasoning_content, end='', flush=True)
|
|||
|
reasoning_content += delta.reasoning_content
|
|||
|
else:
|
|||
|
# 开始回复
|
|||
|
if delta.content != "" and is_answering is False:
|
|||
|
print("\n" + "=" * 20 + "完整回复" + "=" * 20 + "\n")
|
|||
|
is_answering = True
|
|||
|
# 打印回复过程
|
|||
|
print(delta.content, end='', flush=True)
|
|||
|
answer_content += delta.content
|
|||
|
|
|||
|
ggb = f"{output_dir}/GGB.txt"
|
|||
|
with open(ggb, "w", encoding='utf-8') as f:
|
|||
|
f.write(answer_content)
|
|||
|
return ggb
|