Skip to content

Commit af3f19d

Browse files
committed
images
1 parent b6cce8b commit af3f19d

File tree

3 files changed

+134
-0
lines changed

3 files changed

+134
-0
lines changed

articles/ai-foundry/model-inference/includes/use-structured-outputs/python.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,140 @@ except ValidationError as e:
239239
print(f"Validation error: {e}")
240240
```
241241

242+
## Structured outputs in images
243+
244+
You can use structured outputs with multi-modal models to extract information from data like images. Let's consider the following chart:
245+
246+
:::image type="content" source="../../media/use-structured-outputs/example_graph_treecover.png" alt-text="An example image showing a chart with the annual loss in thousand square kilometers of global tree cover across different climate zones." lightbox="../../media/use-structured-outputs/example_graph_treecover.png":::
247+
248+
Let's load this image:
249+
250+
```python
251+
from azure.ai.inference.models import ImageContentItem, ImageUrl
252+
253+
image_graph = ImageUrl.load(
254+
image_file="example_graph_treecover.png",
255+
image_format="png"
256+
)
257+
```
258+
259+
Let's define a generic schema that can be use to encode the information contained in a chart. We use [Pyndatic objects](#use-pydantic-objects) as described before.
260+
261+
```python
262+
from pydantic import BaseModel
263+
264+
class DataPoint(BaseModel):
265+
x: float
266+
y: float
267+
serie: str
268+
269+
class Graph(BaseModel):
270+
title: str
271+
description: str
272+
x_axis: str
273+
y_axis: str
274+
legend: list[str]
275+
data: list[DataPoint]
276+
```
277+
278+
Let's use structured outputs to extract the information:
279+
280+
```python
281+
response = client.complete(
282+
response_format=JsonSchemaFormat(
283+
name="graph_schema",
284+
schema=Graph.model_json_schema(),
285+
description="Describes the data in the graph",
286+
strict=False,
287+
),
288+
messages=[
289+
SystemMessage("""
290+
Extract the information from the graph. Extrapolate the values of the x axe to ensure you have the correct number
291+
of data points for each of the years from 2001 to 2023. Scale the values of the y axes to account for the values
292+
being stacked.
293+
"""
294+
),
295+
UserMessage(content=[ImageContentItem(image_url=image_graph)]),
296+
],
297+
)
298+
```
299+
300+
Let's check the outputs:
301+
302+
```python
303+
import json
304+
305+
json_response_message = json.loads(response.choices[0].message.content)
306+
data = Graph.model_validate(json_response_message)
307+
print(json.dumps(json_response_message, indent=4))
308+
```
309+
310+
```output
311+
{
312+
"title": "Global tree cover: annual loss",
313+
"description": "Annual loss in thousand square kilometers of global tree cover across different climate zones.",
314+
"x_axis": "Year",
315+
"y_axis": "Thousand square kilometers",
316+
"legend": [
317+
"Boreal",
318+
"Temperate",
319+
"Subtropical",
320+
"Tropical"
321+
],
322+
"data": [
323+
{
324+
"x": 2001,
325+
"y": -35,
326+
"serie": "Boreal"
327+
},
328+
{
329+
"x": 2001,
330+
"y": -10,
331+
"serie": "Temperate"
332+
},
333+
{
334+
"x": 2001,
335+
"y": -55,
336+
...
337+
"serie": "Tropical"
338+
}
339+
]
340+
}
341+
```
342+
343+
Let's use `matplotlib` and try to plot the data:
344+
345+
```python
346+
import matplotlib.pyplot as plt
347+
import pandas as pd
348+
349+
# Convert data to a DataFrame for easier manipulation
350+
df = pd.DataFrame(data.model_dump()["data"])
351+
352+
# Pivot the data to prepare for stacked bar chart
353+
pivot_df = df.pivot(index="x", columns="serie", values="y").fillna(0)
354+
355+
# Plotting
356+
fig, ax = plt.subplots(figsize=(10, 6))
357+
358+
# Stacked bar chart
359+
pivot_df.plot(kind="bar", stacked=True, ax=ax, color=["#114488", "#3CB371", "#1188AA", "#006400"])
360+
361+
# Chart customization
362+
ax.set_title(data.title, fontsize=16)
363+
ax.set_xlabel(data.x_axis, fontsize=12)
364+
ax.set_ylabel(data.y_axis, fontsize=12)
365+
ax.legend(title=data.legend, fontsize=10)
366+
ax.grid(axis="y", linestyle="--", alpha=0.7)
367+
368+
# Show the plot
369+
plt.tight_layout()
370+
plt.show()
371+
```
372+
373+
:::image type="content" source="../../media/use-structured-outputs/graph_treecover_plot.png" alt-text="The resulting plot of the data contained in the structured output generated by the model." lightbox="../../media/use-structured-outputs/graph_treecover_plot.png":::
374+
375+
242376
### Supported schemas
243377

244378
There are some limitations that models may place in how schemas are defined. When using structure outputs, consider the following limitations. Notice that limitations may vary per model.
84.1 KB
Loading
50 KB
Loading

0 commit comments

Comments
 (0)