File size: 9,108 Bytes
a1384c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3668318
 
a1384c3
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# app.py
import gradio as gr
import requests
import base64
import os
import openai
from datetime import datetime
import random
import re
import markdown

# 设置 API 密钥(通过 Hugging Face Space Secrets 配置)
API_KEY = os.getenv("BAIDU_API_KEY")
SECRET_KEY = os.getenv("BAIDU_SECRET_KEY")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")

# 百度 OCR 接口
def get_access_token(api_key, secret_key):
    url = "https://aip.baidubce.com/oauth/2.0/token"
    params = {
        "grant_type": "client_credentials",
        "client_id": api_key,
        "client_secret": secret_key
    }
    response = requests.post(url, params=params)
    return response.json().get("access_token")

def ocr_image(image_path, access_token):
    with open(image_path, "rb") as f:
        img_data = base64.b64encode(f.read()).decode()
    
    url = f"https://aip.baidubce.com/rest/2.0/ocr/v1/handwriting?access_token={access_token}"
    headers = {"Content-Type": "application/x-www-form-urlencoded"}
    data = {
        "image": img_data,
        "language_type": "ENG"
    }
    response = requests.post(url, headers=headers, data=data)
    return response.json()

# GPT 处理函数
def process_with_gpt(prompt):
    client = openai.OpenAI(
        api_key=OPENAI_API_KEY,
        base_url="https://api.openai.com/v1"
    )
    
    completion = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.7
    )
    return completion.choices[0].message.content

# 主处理流程
def process_essay(image):
    # 生成文件名
    now = datetime.now().strftime("%Y%m%d%H%M%S")
    code = f"{random.randint(0000,9999):04}"
    file_name = "#" + str(code) + "-" + now
    
    # 临时保存上传的文件
    temp_path = f"temp_{code}.jpg"
    with open(temp_path, "wb") as f:
        f.write(image.read())
    
    try:
        # OCR 识别
        access_token = get_access_token(API_KEY, SECRET_KEY)
        result = ocr_image(temp_path, access_token)
        
        if "words_result" not in result:
            return "OCR 识别失败,请检查图片内容"
            
        essay_text = "\n".join([item["words"] for item in result["words_result"]])
        
        # 格式整理
        format_prompt = (
            "请帮我整理下面的英语作文文本格式,只整理英文正文部分(忽略英文正文外所有部分),"
            "保证原汁原味(明显错误空格换行、乱码、非常用字符比如☰需要改正除外),"
            "出现的拼写错误也不要帮助改正:\n\n" + essay_text
        )
        revised_text = process_with_gpt(format_prompt)
        
        # 语法纠正
        correction_prompt = (
            "请帮我把下面的英语作文的语法错误改正,输出改正后的文章(只改错误和不流畅之处),"
            "请参照下面的格式要求\n"
            "格式要求:原文修改部分用()括起来,修改的部分用[]括起来,修改单词括单词、"
            "修改短语括短语、修改句子括句子,括的部分精准一些,能反映问题\n"
            "示例:The (rabbish) [rubbish] thrown by visitors has piled up and its lush (verdure no longer flourish) [verdure no longer flourishes] as it (did once) [once did].\n\n"
            "需要批改的英语习作:\n" + revised_text
        )
        corrected_text = process_with_gpt(correction_prompt)
        
        # 批改意见
        assessment_prompt = """
        下面是一份已经批改过的英语作文(改正了一些语法错误和不流畅不准确之处),其中小括号表示原文的错误,
        中括号表示原文的修改部分。请你根据修改的批注,按照如下格式给出批改意见:
        > 英文有错误的原文1
        - 错误1和解决方案
        - 错误2和解决方案,后面的以此类推
        示例:
        > The rabbish thrown by visitors has piled up and its lush verdure no longer flourish as it did once.
        - rabbish:拼写错误
        - verdure no longer flourish:动词单复数错误,其中verdure是单数,动词使用第三人称单数
        - as it did once:语序错误
        
        实际批改内容:
        """ + corrected_text
        
        assessment_text = process_with_gpt(assessment_prompt)
        
        # 评分系统
        rate_prompt = """
        你是资深英语写作批改专家,按以下三个维度评分(F/B-/B/B+/A-/A/A+等级):
        ## 语言通顺度(Fluency)&可读性与风格(Readability & Style)
        ## 上下文连贯度(Coherence)
        ## 词汇多样性(Lexical Resource)&语法准确性(Grammatical Accuracy)
        要求:1. 给出评分等级 2. 详细分析原因 3. 提出改进方向
        示例格式:
        ## 语言通顺度 B+
        - 优点说明...
        - 缺点说明...
        - 改进建议...
        
        需要评分的作文:
        """ + revised_text
        
        rate_text = process_with_gpt(rate_prompt)
        
        # 优秀范文
        rewrite_prompt = """
        请使用优秀的英语表达重写下面这篇英文习作,要展现优秀的词汇和语法,使用地道的表达方式,
        使用多样化的句式、短语和词汇,加粗可供学习的部分。
        原文:
        """ + revised_text
        
        perfect_text = process_with_gpt(rewrite_prompt)
        
        # 推荐表达
        theme_prompt = """
        请分析作文内容并给出主题相关的优秀表达:
        1. 推测作文主题
        2. 分析具体内容
        3. 提供相关优秀表达(包含句子、句型、短语、词汇)
        
        需要分析的作文:
        """ + revised_text
        
        theme_text = process_with_gpt(theme_prompt)
        theme_text = theme_text.split("## 可用表达")[1] if "## 可用表达" in theme_text else ""
        
        # HTML 生成
        def highlight_brackets(text):
            text = re.sub(r'\[([^\[\]]+)\]', r'<span style="background:#d4f7d4">\1</span>', text)
            text = re.sub(r'\(([^\(\)]+)\)', r'<span style="background:#ffd6d6">\1</span>', text)
            return text.replace('\n', '<br>')
        
        # 图片 Base64 编码
        with open(temp_path, "rb") as img_f:
            img_b64 = base64.b64encode(img_f.read()).decode()
            img_html = f'<img src="data:image/jpeg;base64,{img_b64}" style="width:100%;max-height:600px;object-fit:contain;margin:20px 0">'
        
        # 组合最终 HTML
        final_html = f"""
        <html>
        <style>
            body {{ font-family: Arial, sans-serif; line-height: 1.6; padding: 20px; }}
            .section {{ margin-bottom: 30px; }}
            code {{ background: #f5f5f5; padding: 2px 4px; border-radius: 4px; }}
            pre {{ background: #f5f5f5; padding: 10px; overflow-x: auto; }}
            blockquote {{ border-left: 4px solid #ddd; padding-left: 12px; color: #666; }}
        </style>
        <body>
            <h1>作文批改结果 #{code}</h1>
            {img_html}
            
            <div class="section">
                <h2>批改结果</h2>
                <div style="font-family:Consolas,monospace;">{highlight_brackets(corrected_text)}</div>
            </div>
            
            <div class="section">
                <h2>批改意见</h2>
                <div style="font-family:Consolas,monospace;">{markdown.markdown(assessment_text)}</div>
            </div>
            
            <div class="section">
                <h2>评分分析</h2>
                <div style="font-family:Consolas,monospace;">{markdown.markdown(rate_text)}</div>
            </div>
            
            <div class="section">
                <h2>优秀范文</h2>
                <div style="font-family:Consolas,monospace;">{markdown.markdown(perfect_text)}</div>
            </div>
            
            <div class="section">
                <h2>推荐表达</h2>
                <div style="font-family:Consolas,monospace;">{markdown.markdown(theme_text)}</div>
            </div>
        </body>
        </html>
        """
        
        return final_html
        
    finally:
        # 清理临时文件
        if os.path.exists(temp_path):
            os.remove(temp_path)

# 创建 Gradio 界面
def create_interface():
    description = """
    英语作文批改助手
    上传一张包含英语作文的手写图片,系统将自动进行文字识别并提供详细的批改建议、评分和优秀范文。
    """
    
    interface = gr.Interface(
        fn=process_essay,
        inputs=gr.File(label="上传作文图片(JPG/PNG)", type="file"),
        outputs=gr.HTML(label="批改结果"),
        title="英语作文智能批改",
        description=description,
        #examples=[["example.jpg"]],
        #cache_examples=False,
        theme="default"
    )
    
    return interface

if __name__ == "__main__":
    create_interface().launch()