Building A Real-Time Data Visualization Solution With Generative AI - by Yi Ai - Medium
Building A Real-Time Data Visualization Solution With Generative AI - by Yi Ai - Medium
Open in app
Member-only story
Yi Ai Follow
This article demonstrates how to build a data visualization system that uses
LangChain with LLMs to transform queries into interactive visual insights. The
system integrates OpenAI’s GPT-4o-mini for query interpretation and data
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 1/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
Prerequisites
Before we begin, ensure you have the following installed:
Necessary Python libraries: Install them using the following pip command:
Architecture Overview
Before diving into the implementation, let’s understand the architecture of our data
visualization agent.
Components
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 2/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
1. User Interface (Streamlit): Allows users to input queries and display results.
6. Data Transformer: Uses GPT-4o-mini to transform the SQL query results into a
format suitable for the recommended visualization.
Workflow
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 3/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 4/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 5/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
9. Output: The user interface displays the answer, visualization, and map (if
applicable).
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 6/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
dob DATE,
gender STRING,
create_timestamp TIMESTAMP
);
service_account_file = os.environ["GOOGLE_APPLICATION_CREDENTIALS"]
project = os.environ["GOOGLE_PROJECT"]
dataset = os.environ["BIGQUERY_DATASET"]
sql_url = (
f"bigquery://{project}/{dataset}?credentials_path={service_account_file}"
)
db = SQLDatabase.from_uri(sql_url)
Text-to-SQL
We start by converting natural language questions into SQL queries using the LLM
model:
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 7/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
sql_prompt = PromptTemplate.from_template("""
You are a SQL expert with access to a BigQuery dataset containing c
Given an input question, generate a syntactically correct SQL query
Question: {input}
Guidelines:
1. Ensure that all attribute searches are case-insensitive.
2. ALWAYS add 'LIMIT {top_k}' at the end of the query unless:
- The question explicitly asks for all records
- The query uses GROUP BY and needs to show all groups
- The query is counting records (using COUNT)
- The query calculates aggregates that need all data
Double check the user's sql query for common mistakes, including:
- Using NOT IN with NULL values
- Using UNION when UNION ALL should have been used
- Using BETWEEN for exclusive ranges
- Data type mismatch in predicates
- Properly quoting identifiers
- Using the correct number of arguments for functions
- Casting to the correct data type
- Using the proper columns for joins
- Missing LIMIT clause when returning raw records
Provide only the final SQL query as plain text without any formatti
If the question is not about customers or addresses, respond with "
""")
text_to_sql = create_sql_query_chain(
model, db, sql_prompt)
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 8/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
@RunnableLambda
def execute_query(result, config):
dispatch_custom_event(
"process.execute_query",
{
"status": ""
},
config=config
)
return {
**result,
'result': db.run_no_throw(
command=result["query"], include_columns=True)
}
Extracting Coordinates
If the query results include geographical data, we extract latitude and longitude for
map visualizations:
try:
if isinstance(result_str, str):
result_data = eval(result_str)
else:
result_data = result_str
except Exception as e:
print(f"Error evaluating result string: {e}")
return None
unique_lat_values = set()
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 9/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
unique_long_values = set()
except Exception as e:
print(f"Error extracting coordinates: {e}")
return None
Recommending Visualizations
We use LLM to recommend the most suitable visualization based on the user’s
question, SQL query, and results:
viz_prompt = PromptTemplate.from_template("""
You are an AI assistant that recommends appropriate data visualizations for cus
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 10/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
Special Cases:
1. Geographic Data:
* If result contains latitude and longitude → No chart (will display map)
* For address/location questions → No chart (will display map)
2. Raw Data:
* Individual customer records → No chart (tabular display)
* Non-aggregated data → No chart (tabular display)
Tables in scope:
- customer: customer_key, first_name, last_name, source_system_name, dob, gende
- customer_address: customer_key, address_key
- address: address_key, full_address, state, country, latitude, longitude
Question: {question}
SQL Query: {query}
SQL Result: {result}
@RunnableLambda
def transform_data_for_visualization_chain(args, config):
try:
dispatch_custom_event(
"process.transform_data_for_visualization_chain",
{
"status": ""
},
config=config
)
chart_type = args.get("visualization").get("type")
result = args.get("result")
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 11/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
if chart_type == 'bar':
transform_prompt = bar_prompt
elif chart_type == 'horizontal_bar':
transform_prompt = horizontal_bar_prompt
elif chart_type == 'pie':
transform_prompt = pie_prompt
elif chart_type == 'scatter':
transform_prompt = scatter_prompt
elif chart_type == 'line':
transform_prompt = line_prompt
else:
transform_prompt = None
assign_chart_type_and_result = RunnableLambda(
lambda args: {**args, "chart_type": args.get("visualization", {}).g
"type"), "result": args.get("result")}
)
if transform_prompt:
transform_chain = (
assign_chart_type_and_result
| transform_prompt
| model
)
return transform_chain
except Exception as e:
print(e)
print(f"Error in transform_data_for_visualization: {e}")
return {"chart_data": None}
viz_prompt
| model
| parse_visualization_response
def create_data_transform_prompt(self):
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 12/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
Your response must be a valid JSON object containing ONLY the chart_d
"""
chart_prompts = {
"bar": """For a bar chart, return JSON in this EXACT format:
{{
"chart_data": {{
"labels": ["Category1", "Category2", ...],
"values": [
{{
"data": [number1, number2, ...],
"label": "Metric Name"
}}
]
}}
}}
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 13/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
"chart_data": {{
"labels": ["Category1", "Category2", ...],
"values": [
{{
"data": [number1, number2, ...],
"label": "Metric Name"
}}
]
}}
}}
Example:
{{
"chart_data": {{
"labels": ["Male", "Female"],
"values": [
{{
"data": [75000, 78000],
"label": "Customer Count"
}}
]
}}
}}""",
Example:
{{
"chart_data": {{
"xValues": ["2023-01", "2023-02", "2023-03", "2023-04"],
"yValues": [
{{
"data": [12500, 13600, 14800, 15200],
"label": "Monthly Registrations"
}}
]
}}
}}
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 14/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
Example:
{{
"chart_data": [
{{
"value": 150,
"label": "System A"
}},
{{
"value": 45,
"label": "System B"
}},
{{
"value": 25,
"label": "System C"
}}
]
}}""",
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 15/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
],
"label": "Series Name"
}}
]
}}
}}
Example:
{{
"chart_data": {{
"series": [
{{
"data": [
{{
"x": -33.865,
"y": 151.209,
"id": 1
}},
{{
"x": -37.813,
"y": 144.963,
"id": 2
}},
{{
"x": -27.470,
"y": 153.021,
"id": 3
}}
],
"label": "Customer Locations"
}}
]
}}
}}
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 16/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
}},
{{
"data": [
{{
"x": -27.470,
"y": 153.021,
"id": 3
}},
{{
"x": -31.950,
"y": 115.860,
"id": 4
}}
],
"label": "Female Customers"
}}
]
}}
}}"""
}
return (
PromptTemplate.from_template(bar_prompt),
PromptTemplate.from_template(horizontal_bar_prompt),
PromptTemplate.from_template(pie_prompt),
PromptTemplate.from_template(scatter_prompt),
PromptTemplate.from_template(line_prompt)
)
@RunnableLambda
def transform_data_for_visualization_chain(args, config):
try:
dispatch_custom_event(
"process.transform_data_for_visualization_chain",
{
"status": ""
},
config=config
)
chart_type = args.get("visualization").get("type")
result = args.get("result")
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 17/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
if chart_type == 'bar':
transform_prompt = bar_prompt
elif chart_type == 'horizontal_bar':
transform_prompt = horizontal_bar_prompt
elif chart_type == 'pie':
transform_prompt = pie_prompt
elif chart_type == 'scatter':
transform_prompt = scatter_prompt
elif chart_type == 'line':
transform_prompt = line_prompt
else:
transform_prompt = None
assign_chart_type_and_result = RunnableLambda(
lambda args: {**args, "chart_type": args.get("visualization", {}).g
"type"), "result": args.get("result")}
)
if transform_prompt:
transform_chain = (
assign_chart_type_and_result
| transform_prompt
| model
)
return transform_chain
except Exception as e:
print(e)
print(f"Error in transform_data_for_visualization: {e}")
return {"chart_data": None}
create_answer_prommpt = PromptTemplate.from_template(
"""Given the following user question, corresponding SQL query, and
Question: {question}
SQL Query: {query}
SQL Result: {result}
Answer: """
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 18/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
)
create_answer_prommpt | model
@RunnableLambda
def format_final_result(result, config):
try:
dispatch_custom_event(
"process.format_final_result",
{
"status": ""
},
config=config
)
if isinstance(result, str):
try:
result = json.loads(result)
except json.JSONDecodeError:
result = {"answer": result}
answer = ""
chart_data = None
chart_type = None
coordinates = None
chart_data_msg = result.get('chart_data')
if hasattr(chart_data_msg, 'content'):
try:
content = chart_data_msg.content
content = content.replace(
'```json', '').replace('```', '').strip()
parsed_data = json.loads(content)
if isinstance(parsed_data, dict) and 'chart_data' in parsed
chart_data = parsed_data['chart_data']
except json.JSONDecodeError:
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 19/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
answer_msg = result.get('answer')
if hasattr(answer_msg, 'content'):
answer = answer_msg.content
elif isinstance(answer_msg, str):
answer = answer_msg
elif isinstance(answer_msg, dict) and 'content' in answer_msg:
answer = answer_msg['content']
else:
result_data = result.get("result", {})
if isinstance(result_data, dict) and "result" in result_data:
answer = str(result_data["result"])
else:
answer = str(result_data)
response_dict = {
"answer": answer,
"coordinates": coordinates,
"chart_data": chart_data,
"chart_type": chart_type
}
return json.dumps(response_dict)
except Exception as e:
print(f"Error in format_final_result: {e}")
return json.dumps({
"answer": "Error formatting result",
"coordinates": None,
"chart_data": None,
"chart_type": None
})
chain = (
RunnablePassthrough().assign(query=text_to_sql)
| RunnablePassthrough().assign(
result=execute_query
)
| RunnablePassthrough().assign(
coordinates=lambda x: extract_coordinates(x)
)
| RunnablePassthrough.assign(
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 20/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
visualization=RunnableLambda(
lambda x: {
"question": x.get("question", ""),
"query": x["query"],
"result": x.get("result", {}).get("result")
}
)
| viz_prompt
| model
| parse_visualization_response
)
| RunnablePassthrough().assign(
chart_data=transform_data_for_visualization_chain
)
| RunnablePassthrough.assign(
answer=create_answer_prommpt | model
)
| format_final_result
| StrOutputParser()
)
While I won’t be providing the complete source code for the Streamlit app in this
article, you can find the example code here. In this section, we’ll focus specifically
on how to extend Streamlit with Lanchain Streaming API and custom event handlers
to enhance user interaction and provide real-time feedback.
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 21/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
class CustomStreamlitCallbackHandler(StreamlitCallbackHandler):
def on_custom_event(self, name: str, data: dict, **kwargs):
"""Handle custom events, update labels, and mark as complete if specifi
if self._current_thought is not None:
custom_event_label = f"💡{name}"
self._current_thought.container.update(
new_label=custom_event_label)
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 22/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
@RunnableLambda
def execute_query(query, config):
# Send custom event
dispatch_custom_event(
"process.execute_query",
{"status": "Executing SQL query..."},
config=config
)
try:
result = db.run_query(query)
dispatch_custom_event(
"process.execute_query",
{"status": "SQL query executed successfully.", "is_complete": True}
config=config
)
return result
except Exception as e:
dispatch_custom_event(
"process.execute_query",
{"status": f"Error executing SQL query: {e}", "is_complete": True},
config=config
)
return None
except Exception as e:
st.error(f"Error processing query: {str(e)}")
return {"answer": "Sorry, I encountered an error processing your query.
with st.chat_message("assistant"):
response = process_query(prompt, assistant)
if response is not None:
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 23/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
Check out how the data and charts are generated based on data from the BigQuery
dataset. The application connects to the BigQuery dataset, executes the generated
SQL queries, and displays dynamic visualizations and maps accordingly. The custom
event handlers provide real-time feedback in the Streamlit interface, enhancing the
interactivity and user experience.
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 24/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
Conclusion
This visualization solution streamlines the data analysis workflow, making it
accessible even to users without extensive technical expertise. You can enhance this
agent further by incorporating additional visualization types, integrating more data
sources, or improving its natural language understanding capabilities. Enjoy
exploring its possibilities!
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 25/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
Follow
Written by Yi Ai
719 followers · 49 following
A Technology Enthusiast
Responses (2)
omar abdeddaim
Arlene Watson
May 22
Sorry to be a negative nancy here... just wanted to mention couple caveats not shared on this article.
1. Text-to-SQL is not reliable. Unless your model is trained (ex. fine-tuning, few-shot or RAG), it won't
generate consistent or reliable result… more
1 Reply
Alan Whitehouse
Feb 11 (edited)
Great post. Question, relating to the chart prompts. Is there a library someplace that contains how to best
build/structure prompts for all the different charts that plotly supports? If not, any tips on how to best
structure the prompt for charts… more
Reply
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 26/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
More from Yi Ai
Yi Ai
Apr 19 10 2
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 27/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
In GoPenAI by Yi Ai
Aug 7 56
In GoPenAI by Yi Ai
Sep 7 56
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 28/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
In GoPenAI by Yi Ai
Apr 2 163 2
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 29/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
Structured LLM Outputs Made Easy: Building a Slack Digest Agent with
Pydantic AI
As developers and AI practitioners, many of us belong to vibrant online communities, like the
MLOps Community on Slack. These platforms are…
Apr 15 53
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 30/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
6d ago 1.6K 36
Malini Anbazhagan
Jun 12 22 2
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 31/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
Apr 17 2.8K 35
CSV Plot Agent with LangChain & Streamlit: Your Introduction to Data
Agents
How you can learn the basics of tool-based agents with LangChain, GPT-4o-mini and Streamlit.
Sep 22 122 4
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 32/33
02/10/2025 15:56 Building a Real-Time Data Visualization Solution with Generative AI | by Yi Ai | Medium
3d ago 1
https://yia333.medium.com/building-a-real-time-data-visualization-solution-with-generative-ai-4a560f603696 33/33