The goal here is to use Gen AI to graph install reports of various distro, like Linux and others. Reports are CVS, cretaed from somewhere else, example here is some specific format.
So OCI Gen AI service should be able to use them to create a graph, such as a bar chart, pie chart, or something similar.
So here we have:
- OCI Generative AI service
- Responses API, it's endpoint you call in for this service, ask model to do work
- Files API, another endpoint to get files to work with
- Code Interpreter, like temporary container, gives model Python execution environment
You need the project OCID for later use.

You need the API key OCID for later use. You also need the key value itself. Save it when it is created, because it will not be available afterward.

A new policy for the API key is required. Example.
allow any-user to manage generative-ai-family in compartment zarko-compartment where all { request.principal.type='generativeaiapikey', request.principal.id='ocid1.generativeaiapikey.oc1.region.key...ocid' }
The first idea was to upload the CSV to the Gen AI, using Files API. I tried
1. upload CSV but OCI rejected it
2. upload TXT but OCI rejected it
3. upload PDF and upload worked, but processing failed. Seems only PDF is supported.
Next I do is to open the CSV file in Python, read its contents into a string, and send that string inside the prompt to Gen AI.
In the same folder, it's CSV report and Python program that asks Gen AI service to creates a report.
On the host where you run it, you need Python modules such as openai, oci, oci-openai, httpx,
and later we need panda, io, matplotlib.
Example of cvs report
hostname-1,Linux,user-1,user-1,user-3,111
hostname-1,Linux,user-a,user-b,user-c,22
hostname-1,Ubuntu,user-aa,user-bb,user-cc,3
$ ask-oci-for-graph.py -h
usage: ask-oci-for-graph.py [-h] [--project-id PROJECT_ID] [--api-key API_KEY] [--region REGION] [--model MODEL]
csv_file
Ask OCI Gen AI to create graphs from CSV
positional arguments:
csv_file Path to combined CSV file
optional arguments:
-h, --help show this help message and exit
--project-id PROJECT_ID
--api-key API_KEY
--region REGION
--model MODEL
#!/usr/bin/env python3
import argparse
import os
import sys
from pathlib import Path
from openai import OpenAI
def parse_args():
parser = argparse.ArgumentParser(
description="Ask OCI Gen AI to create graphs from CSV"
)
parser.add_argument("csv_file", help="Path to combined CSV file")
parser.add_argument("--project-id", default=os.environ.get("OCI_GENAI_PROJECT_ID"))
parser.add_argument("--api-key", default=os.environ.get("OCI_GENAI_API_KEY"))
parser.add_argument("--region", default="us-phoenix-1")
parser.add_argument("--model", default=os.environ.get("OCI_GENAI_MODEL", "google.gemini-2.5-flash"))
return parser.parse_args()
def make_client(region, project_id, api_key):
return OpenAI(
base_url=f"https://inference.generativeai.{region}.oci.oraclecloud.com/openai/v1",
api_key=api_key,
project=project_id,
)
def read_csv_text(csv_path):
with open(csv_path, "r", encoding="utf-8") as f:
return f.read()
def save_text(path, text):
path.write_text(text or "", encoding="utf-8")
def main():
args = parse_args()
csv_path = Path(args.csv_file).resolve()
outdir = csv_path.parent
if not csv_path.exists():
print(f"CSV file not found: {csv_path}", file=sys.stderr)
return 1
if not args.project_id:
print("Missing --project-id or OCI_GENAI_PROJECT_ID", file=sys.stderr)
return 1
if not args.api_key:
print("Missing --api-key or OCI_GENAI_API_KEY", file=sys.stderr)
return 1
print("Reading CSV...")
csv_text = read_csv_text(csv_path)
print("Creating OCI client...")
client = make_client(args.region, args.project_id, args.api_key)
summary_prompt = f"""
Read this CSV data.
The file may contain duplicate header rows because it may have been combined with plain cat.
Ignore repeated header rows like:
Site,OS Type,User,Mgr1,Mgr2,Mgr3,Installs
Expected columns:
- Site
- OS Type
- User
- Mgr1
- Mgr2
- Mgr3
- Installs
Return only a concise summary with:
1. total installs by Site
2. total installs by OS Type
3. top 10 users by Installs
4. manager chain Mgr1, Mgr2, Mgr3 for the top 10 users
CSV data:
{csv_text}
"""
print("Request 1: summary...")
summary_response = client.responses.create(
model=args.model,
input=summary_prompt,
)
summary_text = getattr(summary_response, "output_text", "") or ""
summary_file = outdir / "oci_summary.txt"
save_text(summary_file, summary_text)
print(f"Saved: {summary_file}")
chart_prompt = f"""
Read this CSV data.
The file may contain duplicate header rows because it may have been combined with plain cat.
Ignore repeated header rows like:
Site,OS Type,User,Mgr1,Mgr2,Mgr3,Installs
Expected columns:
- Site
- OS Type
- User
- Mgr1
- Mgr2
- Mgr3
- Installs
Use Python to parse the CSV data and create:
1. a stacked bar chart by Site split into Linux and Solaris/AK
2. a horizontal bar chart of top 10 users (like User,Mgr1,Mgr2,Mgr3) by Installs
3. a short summary
4. Save the charts as PNG files
If file outputs are supported, save charts as PNG files and mention the filenames.
Again, we wan't User,Mgr1,Mgr2,Mgr3 on PNG files.
CSV data:
{csv_text}
"""
print("Request 2: charts...")
chart_response = client.responses.create(
model=args.model,
tools=[{"type": "code_interpreter"}],
instructions="Use Python to analyze the CSV text and generate charts.",
input=chart_prompt,
)
chart_text = getattr(chart_response, "output_text", "") or ""
chart_file = outdir / "oci_charts.txt"
save_text(chart_file, chart_text)
print(f"Saved: {chart_file}")
print("Done.")
return 0
if __name__ == "__main__":
sys.exit(main())
The program worked well. It successfully uploaded the CSV to OCI and the model (gemini) analyzed it correctly. However, it could not generate graphs due to issues in its execution environment, likely because Python modules were missing. The model did provide Python code to generate the graphs locally, and that worked correctly.
#!/usr/bin/env python3
import pandas as pd
import io
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
# Provided CSV data
csv_data = """Host,OS,User,Mgr1,Mgr2,Mgr3,Installs
hostname-1,Linux,user-1,user-1,user-3,111
hostname-1,Linux,user-a,user-b,user-c,22
hostname-1,Ubuntu,user-aa,user-bb,user-cc,3
"""
# Read the CSV data into a pandas DataFrame
df = pd.read_csv(io.StringIO(csv_data))
# Remove rows that are duplicates of the header.
# This filters out rows where the 'Site' column is literally 'Site',
# indicating a repeated header that was read as data.
df = df[df['Site'] != 'Site'].copy()
# Convert 'Installs' column to numeric.
# Errors are coerced to NaN, and then rows with NaN in 'Installs' are dropped.
# Finally, convert to integer type.
df['Installs'] = pd.to_numeric(df['Installs'], errors='coerce')
df.dropna(subset=['Installs'], inplace=True)
df['Installs'] = df['Installs'].astype(int)
# --- 1. Stacked bar chart by Site split into Linux and Solaris/AK ---
# Group by 'Site' and 'OS Type' and sum 'Installs'
site_os_installs = df.groupby(['Site', 'OS Type'])['Installs'].sum().unstack(fill_value=0)
# Ensure both 'Linux' and 'Solaris/AK' columns exist for consistent plotting,
# even if one OS type has no data for a given site.
for os_type in ['Linux', 'Solaris/AK']:
if os_type not in site_os_installs.columns:
site_os_installs[os_type] = 0
# Reorder columns to ensure consistent stacking order in the plot
site_os_installs = site_os_installs[['Linux', 'Solaris/AK']]
plt.figure(figsize=(12, 7))
site_os_installs.plot(kind='bar', stacked=True, figsize=(12, 7))
plt.title('Total Installs by Site and OS Type')
plt.xlabel('Site')
plt.ylabel('Total Installs')
plt.xticks(rotation=45, ha='right')
plt.legend(title='OS Type')
plt.tight_layout()
stacked_bar_chart_filename = 'installs_by_site_os_stacked_bar_chart.png'
plt.savefig(stacked_bar_chart_filename)
plt.clf() # Clear the current figure to prevent plots from overlapping
# --- 2. Horizontal bar chart of top 10 users (User,Mgr1,Mgr2,Mgr3) by Installs ---
# Create a combined 'User Group' column as requested
df['UserGroup'] = df['User'] + ',' + df['Mgr1'] + ',' + df['Mgr2'] + ',' + df['Mgr3']
# Group by 'UserGroup' and sum 'Installs'
user_installs = df.groupby('UserGroup')['Installs'].sum()
# Get the top 10 user groups by installs
top_10_users = user_installs.nlargest(10)
plt.figure(figsize=(12, 8))
# Sort values for the horizontal bar chart to have the largest bar at the top
top_10_users.sort_values().plot(kind='barh', color='skyblue')
plt.title('Top 10 User Groups by Installs')
plt.xlabel('Total Installs')
plt.ylabel('User Group (User, Mgr1, Mgr2, Mgr3)')
plt.tight_layout()
top_10_users_bar_chart_filename = 'top_10_users_by_installs_horizontal_bar_chart.png'
plt.savefig(top_10_users_bar_chart_filename)
plt.clf() # Clear the current figure
# --- 3. Short summary ---
total_installs = df['Installs'].sum()
unique_sites = df['Site'].nunique()
unique_os_types = df['OS Type'].nunique()
unique_users = df['UserGroup'].nunique()
summary_output = f"""
Summary of Installs Data:
----------------------------
Total installs recorded: {total_installs}
Number of unique sites: {unique_sites}
Number of unique OS types: {unique_os_types}
Number of unique user groups: {unique_users}
The data provides insights into software installations, showing their distribution
across different sites and operating system types, and identifies the top contributing
user groups based on the combined 'User,Mgr1,Mgr2,Mgr3' identifier.
"""
# Output the results
print(summary_output)
print(f"Stacked bar chart saved as: {stacked_bar_chart_filename}")
print(f"Horizontal bar chart saved as: {top_10_users_bar_chart_filename}")
Generated graph files, example
top_10_users_by_installs_horizontal_bar_chart.pnginstalls_by_site_os_stacked_bar_chart.png
