@@ -29,7 +29,7 @@ def encode_image_base64(image: np.ndarray) -> str:
2929
3030def extract_chart_llm (
3131 image_path : str ,
32- model : str = "pixtral-12b-2409 "
32+ model : str = "mistral-ocr-latest "
3333) -> Tuple [Dict [str , Any ], float ]:
3434 """
3535 Extract chart data using LLM vision in a single API call.
@@ -64,36 +64,43 @@ def extract_chart_llm(
6464 # Create Mistral client
6565 client = Mistral (api_key = api_key )
6666
67- # Craft extraction prompt
68- prompt = """Analyze this chart image and extract ALL data points .
67+ # Craft extraction prompt - chain of thought for precision
68+ prompt = """You are extracting data from a chart. Be EXTREMELY precise .
6969
70- IMPORTANT INSTRUCTIONS:
71- 1. Read the axis labels and scale carefully
72- 2. For each visible data point (dot, bar, or line vertex), estimate its X and Y values
73- 3. Use the actual axis values, not pixel positions
74- 4. Be precise - read tick marks and interpolate between them
70+ TASK: Extract the X,Y coordinates of EVERY data point marker in this chart.
7571
76- Return ONLY valid JSON in this exact format:
72+ STEP 1 - ANALYZE AXES:
73+ First, identify the axis ranges by reading the tick labels.
74+
75+ STEP 2 - LOCATE MARKERS:
76+ For line charts: find every dot/marker on the line (not the line itself, the markers).
77+ For scatter plots: find every dot.
78+ For bar charts: measure the height of each bar.
79+
80+ STEP 3 - READ VALUES:
81+ For EACH marker, look at its position and read:
82+ - X: What X gridline or tick is it at or between?
83+ - Y: What Y gridline is the marker at? If between gridlines, estimate precisely.
84+
85+ CRITICAL: Do NOT interpolate or assume patterns. Each point may have a UNIQUE value.
86+ Many charts have irregular data - do not assume smooth curves.
87+
88+ Return JSON only:
7789{
78- "chart_type": "line" or "bar" or "scatter",
79- "x_label": "label from X axis or empty string",
80- "y_label": "label from Y axis or empty string",
81- "x_min": minimum X axis value,
82- "x_max": maximum X axis value,
83- "y_min": minimum Y axis value,
84- "y_max": maximum Y axis value,
85- "data": [
86- {"x": 0, "y": 10},
87- {"x": 1, "y": 20},
88- ...
89- ]
90+ "chart_type": "line" or "scatter" or "bar",
91+ "x_label": "axis label",
92+ "y_label": "axis label",
93+ "data": [{"x": val, "y": val}, ...]
9094}
9195
92- Extract ALL visible data points. Do not skip any."""
96+ Example for irregular data:
97+ {"data": [{"x": 0, "y": 5}, {"x": 1, "y": 8}, {"x": 2, "y": 12}, {"x": 3, "y": 15}]}
98+ Note: each Y is different and not following a pattern."""
9399
94100 try :
101+ # Direct extraction with pixtral (OCR doesn't work for charts)
95102 response = client .chat .complete (
96- model = model ,
103+ model = "pixtral-large-latest" ,
97104 messages = [
98105 {
99106 "role" : "user" ,
@@ -104,7 +111,7 @@ def extract_chart_llm(
104111 }
105112 ],
106113 max_tokens = 4096 ,
107- temperature = 0.1 # Low temperature for precision
114+ temperature = 0.0
108115 )
109116
110117 content = response .choices [0 ].message .content .strip ()
0 commit comments