File size: 4,213 Bytes
c001f24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
import json
import requests
import sys
import base64
from typing import List, Optional, Dict, Any

def generate_subjective_questions(image_path: str) -> Optional[Dict[Any, Any]]:
    """
    Transcribes and structures subjective questions from an image using the Gemini API.
    """
    api_key = os.environ.get("GEMINI_API_KEY")
    if not api_key:
        print("Error: GEMINI_API_KEY environment variable is not set.", file=sys.stderr)
        return None

    # Read and encode image
    try:
        with open(image_path, "rb") as image_file:
            encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
    except Exception as e:
        print(f"Error reading image file: {e}", file=sys.stderr)
        return None

    model_id = "gemini-flash-latest"  
    url = f"https://generativelanguage.googleapis.com/v1beta/models/{model_id}:generateContent?key={api_key}"
    headers = {'Content-Type': 'application/json'}

    prompt_text = """
    Analyze the provided image. It contains a list of subjective questions (handwritten or printed).
    
    Task:
    1.  **Transcribe** each question exactly as written.
    2.  **Identify the Topic:** Determine the subject or topic for each question (e.g., "Ascomycetes", "Thermodynamics"). If the header specifies a topic, use that.
    3.  **Structure:** Return the data in the specified JSON format.
    4.  **Numbering:** Use the question number found in the image.
    
    If the image contains multiple questions, extract all of them.
    """

    request_body = {
        "contents": [
            {
                "role": "user",
                "parts": [
                     {
                        "inline_data": {
                            "mime_type": "image/jpeg", # Assuming JPEG/PNG, API is flexible with image/* usually, but let's send jpeg or png based on file if needed, usually jpeg works for generic
                            "data": encoded_string
                        }
                    },
                    {
                        "text": prompt_text
                    }
                ]
            }
        ],
        "generationConfig": {
            "responseMimeType": "application/json",
            "responseSchema": {
                "type": "object",
                "properties": {
                    "success": {"type": "boolean"},
                    "data": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "question_topic": {"type": "string"},
                                "question_html": {"type": "string"},
                                "question_number_within_topic": {"type": "string"}
                            },
                            "required": ["question_topic", "question_html", "question_number_within_topic"]
                        }
                    }
                },
                "required": ["success", "data"]
            }
        }
    }

    try:
        response = requests.post(url, headers=headers, json=request_body, timeout=120)
        response.raise_for_status()

        response_json = response.json()
        
        # Extract text from candidate
        candidate = response_json.get('candidates', [{}])[0]
        content = candidate.get('content', {})
        parts = content.get('parts', [])
        
        if not parts:
            print("Error: Gemini generated no content.")
            return None
            
        text = parts[0]['text']
        return json.loads(text)

    except requests.exceptions.RequestException as e:
        print(f"Error during Gemini API call: {e}", file=sys.stderr)
        if e.response:
             print(f"Response: {e.response.text}", file=sys.stderr)
        return None
    except json.JSONDecodeError as e:
        print(f"Error parsing JSON response: {e}", file=sys.stderr)
        print(f"Raw text: {text}", file=sys.stderr)
        return None

if __name__ == "__main__":
    # Test the function
    result = generate_subjective_questions("Ascomycetes")
    if result:
        print(json.dumps(result, indent=2))