LouieAI Error Handling¶
This notebook demonstrates error handling patterns specific to the LouieAI lui interface.
Setup¶
In [1]:
Copied!
import os
import graphistry
import pandas as pd
from louieai import louie
# Authenticate
g = graphistry.register(
api=3,
server=os.environ.get("GRAPHISTRY_SERVER", "hub.graphistry.com"),
username=os.environ.get("GRAPHISTRY_USERNAME"),
password=os.environ.get("GRAPHISTRY_PASSWORD"),
)
# Create LouieAI interface
lui = louie(g, server_url=os.environ.get("LOUIE_SERVER", "https://den.louie.ai"))
print("✅ LouieAI ready")
import os
import graphistry
import pandas as pd
from louieai import louie
# Authenticate
g = graphistry.register(
api=3,
server=os.environ.get("GRAPHISTRY_SERVER", "hub.graphistry.com"),
username=os.environ.get("GRAPHISTRY_USERNAME"),
password=os.environ.get("GRAPHISTRY_PASSWORD"),
)
# Create LouieAI interface
lui = louie(g, server_url=os.environ.get("LOUIE_SERVER", "https://den.louie.ai"))
print("✅ LouieAI ready")
✅ LouieAI ready
Handling Missing Data¶
In [2]:
Copied!
# Safe pattern for checking if data exists
lui("What is 2+2?") # Text-only response, no DataFrame
# Always check if DataFrame exists before using it
if lui.df is not None:
print(f"DataFrame shape: {lui.df.shape}")
print(lui.df.head())
else:
print("No DataFrame returned (text-only response)")
print(f"Text response: {lui.text}")
# Safe pattern for checking if data exists
lui("What is 2+2?") # Text-only response, no DataFrame
# Always check if DataFrame exists before using it
if lui.df is not None:
print(f"DataFrame shape: {lui.df.shape}")
print(lui.df.head())
else:
print("No DataFrame returned (text-only response)")
print(f"Text response: {lui.text}")
🤖 LouieAI Response
Thread:
D_xsOfLperiNkIYgT_O5bK | Time: 7.5sThe question is a simple arithmetic problem.
No DataFrame returned (text-only response) Text response: The question is a simple arithmetic problem.
Checking for Errors¶
In [3]:
Copied!
# Check if the last query had errors
if lui.has_errors:
print("⚠️ Last query had errors:")
for error in lui.errors:
print(f" - {error}")
else:
print("✅ No errors in last query")
# Check if the last query had errors
if lui.has_errors:
print("⚠️ Last query had errors:")
for error in lui.errors:
print(f" - {error}")
else:
print("✅ No errors in last query")
✅ No errors in last query
Using History for Recovery¶
In [4]:
Copied!
# Make several queries
lui("Create a DataFrame with sales data", pd.DataFrame({"sales": [100, 200, 300]}))
lui("What is the weather today?") # No DataFrame
# Access previous responses
current_df = lui.df # May be None
previous_df = lui[-2].df if len(lui._history) >= 2 else None
# Use the most recent DataFrame available
df = current_df if current_df is not None else previous_df
if df is not None:
print(f"Using DataFrame with shape: {df.shape}")
else:
print("No DataFrame available in recent history")
# Make several queries
lui("Create a DataFrame with sales data", pd.DataFrame({"sales": [100, 200, 300]}))
lui("What is the weather today?") # No DataFrame
# Access previous responses
current_df = lui.df # May be None
previous_df = lui[-2].df if len(lui._history) >= 2 else None
# Use the most recent DataFrame available
df = current_df if current_df is not None else previous_df
if df is not None:
print(f"Using DataFrame with shape: {df.shape}")
else:
print("No DataFrame available in recent history")
🤖 LouieAI Response
Thread:
D_xsOfLperiNkIYgT_O5bK | Time: 8.6sTo provide the current weather, I need to access a reliable source of weather data. However, I don't have direct access to real-time weather data through my available tools. I can guide you on how to find this information or suggest using a weather API or website.
I don't have direct access to real-time weather data, but you can easily check today's weather using a weather website or app like Weather.com, AccuWeather, or a weather API. If you need help with accessing or using a weather API
I don't have direct access to real-time weather data, but you can easily check today's weather using a weather website or app like Weather.com, AccuWeather, or a weather API. If you need help with accessing or using a weather API
Using DataFrame with shape: (3, 1)
Retry Pattern¶
In [5]:
Copied!
def query_with_retry(prompt, data=None, max_retries=3):
"""Query LouieAI with automatic retry on failure."""
for attempt in range(max_retries):
try:
lui(prompt, data)
if not lui.has_errors:
print(f"✅ Success on attempt {attempt + 1}")
return lui.text, lui.df
print(f"⚠️ Attempt {attempt + 1} had errors, retrying...")
except Exception as e:
if attempt < max_retries - 1:
print(f"Attempt {attempt + 1} failed: {e}")
continue
else:
raise
return None, None
# Example usage
text, df = query_with_retry("Analyze this data", pd.DataFrame({"value": [1, 2, 3]}))
def query_with_retry(prompt, data=None, max_retries=3):
"""Query LouieAI with automatic retry on failure."""
for attempt in range(max_retries):
try:
lui(prompt, data)
if not lui.has_errors:
print(f"✅ Success on attempt {attempt + 1}")
return lui.text, lui.df
print(f"⚠️ Attempt {attempt + 1} had errors, retrying...")
except Exception as e:
if attempt < max_retries - 1:
print(f"Attempt {attempt + 1} failed: {e}")
continue
else:
raise
return None, None
# Example usage
text, df = query_with_retry("Analyze this data", pd.DataFrame({"value": [1, 2, 3]}))
✅ Success on attempt 1
Using Traces for Debugging¶
In [6]:
Copied!
# Enable traces to see reasoning steps
lui.traces = True
# Make a query - will show detailed reasoning
lui("Calculate the average of [10, 20, 30, 40, 50]")
print(f"Result: {lui.text}")
# Disable traces for normal operation
lui.traces = False
# Enable traces to see reasoning steps
lui.traces = True
# Make a query - will show detailed reasoning
lui("Calculate the average of [10, 20, 30, 40, 50]")
print(f"Result: {lui.text}")
# Disable traces for normal operation
lui.traces = False
🤖 LouieAI Response
Thread:
D_xsOfLperiNkIYgT_O5bK | Time: 8.8si Splunk connection successfully established.
i LouieAgent::runner
🐛 Input text:::Calculate the average of [10, 20, 30, 40, 50]
🐛 Reading chat history. (is_prepared: True)
🐛 LouieAgent predict with tools: ['GraphAgent', 'CodeAgent', 'TableAIAgent', 'FirecrawlAgent', 'NotebookAgent', 'DatabricksAgent', 'MermaidAgent', 'PerspectiveAgent', 'OpenSearchAgent', 'KeplerAgent', 'SpannerAgent', 'SpannerPassthroughAgent', 'KustoAgent', 'KustoPassthroughAgent', 'PostgresAgent', 'PostgresPassthroughAgent', 'Done', 'Chat'] has_recipes: True has_examples: True
To calculate the average of a list of numbers, I need to sum the numbers and then divide by the count of the numbers.
Plan:
1. Sum the numbers: 10 + 20 + 30 + 40 + 50.
2. Count the numbers: There are 5 numbers.
3. Divide the sum by the count to get the average.
Calculation:
1. Sum = 10 + 20 + 30 + 40 + 50 = 150
2. Count = 5
3. Average = Sum / Count = 150 / 5 = 30
The average of [10, 20, 30
Plan:
1. Sum the numbers: 10 + 20 + 30 + 40 + 50.
2. Count the numbers: There are 5 numbers.
3. Divide the sum by the count to get the average.
Calculation:
1. Sum = 10 + 20 + 30 + 40 + 50 = 150
2. Count = 5
3. Average = Sum / Count = 150 / 5 = 30
The average of [10, 20, 30
i Louie output text: The average of [10, 20, 30, 40, 50] is 30.
Result: To calculate the average of a list of numbers, I need to sum the numbers and then divide by the count of the numbers. Plan: 1. Sum the numbers: 10 + 20 + 30 + 40 + 50. 2. Count the numbers: There are 5 numbers. 3. Divide the sum by the count to get the average. Calculation: 1. Sum = 10 + 20 + 30 + 40 + 50 = 150 2. Count = 5 3. Average = Sum / Count = 150 / 5 = 30 The average of [10, 20, 30
Batch Processing with Error Tracking¶
In [7]:
Copied!
# Process multiple DataFrames with error tracking
datasets = [
pd.DataFrame({"Q1": [100, 150, 200]}),
pd.DataFrame({"Q2": [120, 160, 210]}),
pd.DataFrame({"Q3": [130, 170, 220]}),
pd.DataFrame({"Q4": [140, 180, 230]}),
]
results = []
errors = []
for i, df in enumerate(datasets, 1):
try:
lui(f"Calculate the total for quarter Q{i}", df)
if lui.df is not None:
results.append({"quarter": f"Q{i}", "response": lui.text, "data": lui.df})
else:
errors.append({"quarter": f"Q{i}", "error": "No DataFrame returned"})
except Exception as e:
errors.append({"quarter": f"Q{i}", "error": str(e)})
print("\n📊 Batch Summary:")
print(f"Successful: {len(results)}")
print(f"Failed: {len(errors)}")
# Process multiple DataFrames with error tracking
datasets = [
pd.DataFrame({"Q1": [100, 150, 200]}),
pd.DataFrame({"Q2": [120, 160, 210]}),
pd.DataFrame({"Q3": [130, 170, 220]}),
pd.DataFrame({"Q4": [140, 180, 230]}),
]
results = []
errors = []
for i, df in enumerate(datasets, 1):
try:
lui(f"Calculate the total for quarter Q{i}", df)
if lui.df is not None:
results.append({"quarter": f"Q{i}", "response": lui.text, "data": lui.df})
else:
errors.append({"quarter": f"Q{i}", "error": "No DataFrame returned"})
except Exception as e:
errors.append({"quarter": f"Q{i}", "error": str(e)})
print("\n📊 Batch Summary:")
print(f"Successful: {len(results)}")
print(f"Failed: {len(errors)}")
📊 Batch Summary: Successful: 4 Failed: 0
Safe Access Patterns¶
In [8]:
Copied!
# Pattern 1: Defensive checking
def get_dataframe_safely():
"""Get DataFrame with fallback to empty."""
return lui.df if lui.df is not None else pd.DataFrame()
# Pattern 2: Check multiple attributes
def get_all_results():
"""Get all available results from last query."""
results = {
"text": lui.text,
"has_dataframe": lui.df is not None,
"has_errors": lui.has_errors,
}
if lui.df is not None:
results["df_shape"] = lui.df.shape
results["df_id"] = lui.df_id
return results
# Example usage
lui("Generate sample data")
results = get_all_results()
print("Query results:", results)
# Pattern 1: Defensive checking
def get_dataframe_safely():
"""Get DataFrame with fallback to empty."""
return lui.df if lui.df is not None else pd.DataFrame()
# Pattern 2: Check multiple attributes
def get_all_results():
"""Get all available results from last query."""
results = {
"text": lui.text,
"has_dataframe": lui.df is not None,
"has_errors": lui.has_errors,
}
if lui.df is not None:
results["df_shape"] = lui.df.shape
results["df_id"] = lui.df_id
return results
# Example usage
lui("Generate sample data")
results = get_all_results()
print("Query results:", results)
🤖 LouieAI Response
Thread:
D_xsOfLperiNkIYgT_O5bK | Time: 28.5sTo generate sample data, I can use the CodeAgent to create a sample dataset using a library like Faker or by manually specifying the data structure. This will allow us to create realistic sample data for testing or analysis purposes.
Plan:
1. Decide on the type of sample data needed (e.g., user data, transaction data).
2. Use the CodeAgent to generate the sample data using a suitable library or method.
3. Ensure the data is realistic and useful for the intended purpose.
CodeAgent
Generate a sample dataset using the Faker library. Create a dataframe with columns for 'Name', 'Email', 'Address', and 'Phone Number', and populate it with 100 rows of realistic data.
I successfully generated a sample dataset using the Faker library. The dataset contains 100 rows with columns for 'Name', 'Email', 'Address', and 'Phone Number', ensuring realistic and varied data entries. The resulting dataframe has been saved as an artifact named 'sample_data', ready for further use or analysis. If you need any more data or
Plan:
1. Decide on the type of sample data needed (e.g., user data, transaction data).
2. Use the CodeAgent to generate the sample data using a suitable library or method.
3. Ensure the data is realistic and useful for the intended purpose.
CodeAgent
Generate a sample dataset using the Faker library. Create a dataframe with columns for 'Name', 'Email', 'Address', and 'Phone Number', and populate it with 100 rows of realistic data.
I successfully generated a sample dataset using the Faker library. The dataset contains 100 rows with columns for 'Name', 'Email', 'Address', and 'Phone Number', ensuring realistic and varied data entries. The resulting dataframe has been saved as an artifact named 'sample_data', ready for further use or analysis. If you need any more data or
[CallElement] Generate a sample dataset using the Faker library. Create a dataframe with columns for 'Name', 'Email', 'Address', and 'Phone Number', and populate it with 100 rows of realistic data.
```python
import pandas as pd
from faker import Faker
# Initialize the Faker library
fake = Faker()
# Generate sample data
data = {
'Name': [fake.name() for _ in range(100)],
'Email': [fake.email() for _ in range(100)],
'Address': [fake.address() for _ in range(100)],
'Phone Number': [fake.phone_number() for _ in range(100)]
}
# Create a DataFrame from the generated data
sample_df = pd.DataFrame(data)
# Save the generated DataFrame as an artifact
save_artifact(sample_df, 'sample_data')
# Print a success message
print('Successfully generated a sample dataframe with 100
import pandas as pd
from faker import Faker
# Initialize the Faker library
fake = Faker()
# Generate sample data
data = {
'Name': [fake.name() for _ in range(100)],
'Email': [fake.email() for _ in range(100)],
'Address': [fake.address() for _ in range(100)],
'Phone Number': [fake.phone_number() for _ in range(100)]
}
# Create a DataFrame from the generated data
sample_df = pd.DataFrame(data)
# Save the generated DataFrame as an artifact
save_artifact(sample_df, 'sample_data')
# Print a success message
print('Successfully generated a sample dataframe with 100
📊 DataFrame: B_crQe5JNI (shape: 100 x 4)
Successfully generated a sample dataframe with 100 rows, containing columns for 'Name', 'Email', 'Address', and 'Phone Number'. The dataset was created using the Faker library, ensuring realistic and varied data entries. This process was executed efficiently, with the entire operation completed in approximately 0.3 seconds. The resulting dataframe has been saved as an artifact named 'sample_data', ready for further use or analysis.
Query results: {'text': "Successfully generated a sample dataframe with 100 rows, containing columns for 'Name', 'Email', 'Address', and 'Phone Number'. The dataset was created using the Faker library, ensuring realistic and varied data entries. This process was executed efficiently, with the entire operation completed in approximately 0.3 seconds. The resulting dataframe has been saved as an artifact named 'sample_data', ready for further use or analysis.", 'has_dataframe': False, 'has_errors': False}
/home/lmeyerov/Work/louie-py/src/louieai/auth.py:209: RuntimeWarning: Failed to fetch dataframe B_crQe5JNI from thread D_xsOfLperiNkIYgT_O5bK. URL: http://localhost:8000/api/dthread/D_xsOfLperiNkIYgT_O5bK/df/block/B_crQe5JNI/arrow. Error: HTTPStatusError: Client error '404 Not Found' for url 'http://localhost:8000/api/dthread/D_xsOfLperiNkIYgT_O5bK/df/block/B_crQe5JNI/arrow' For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404 return func(self, *args, **kwargs)
Summary¶
Key error handling patterns for LouieAI:
- Always check
lui.df is not Nonebefore using DataFrames - Use
lui.has_errorsto check for query errors - Access history with
lui[-1],lui[-2]for recovery - Enable
lui.traces = Truefor debugging - Implement retry logic for critical queries
- Use defensive patterns with fallbacks to empty DataFrames