OpenAI Assistants Integration
Use OpenAI Assistants API with LRS-Agents for policy generation and tool execution.
Overview
OpenAI Assistants provide:
Built-in tools (Code Interpreter, File Search, Function Calling)
Persistent threads and message history
Automatic retry logic
LRS-Agents adds:
Precision-adaptive behavior
Automatic adaptation when tools fail
Hierarchical belief tracking
Quick Start
Basic Setup
from openai import OpenAI
from lrs.integration.openai_assistants import (
OpenAIAssistantPolicyGenerator,
create_openai_lrs_agent
)
# Initialize OpenAI client
client = OpenAI(api_key="sk-...")
# Create LRS agent with OpenAI Assistants
agent = create_openai_lrs_agent(
client=client,
model="gpt-4-turbo-preview",
tools=[...], # Your LRS tools
preferences={'success': 5.0, 'error': -3.0}
)
# Run task
result = agent.run(
task="Analyze the uploaded dataset",
max_iterations=20
)
Using Assistants for Policy Generation
Basic Policy Generator
from openai import OpenAI
from lrs.integration.openai_assistants import OpenAIAssistantPolicyGenerator
from lrs.core.registry import ToolRegistry
client = OpenAI(api_key="sk-...")
registry = ToolRegistry()
# Register your tools
registry.register(fetch_tool)
registry.register(process_tool)
registry.register(save_tool)
# Create generator
generator = OpenAIAssistantPolicyGenerator(
client=client,
model="gpt-4-turbo-preview",
registry=registry
)
# Generate proposals
proposals = generator.generate_proposals(
state={'goal': 'Fetch and process data'},
precision=0.5
)
# Proposals are automatically converted to LRS policies
for proposal in proposals:
print(f"Strategy: {proposal['strategy']}")
print(f"Tools: {proposal['tool_names']}")
print(f"Rationale: {proposal['rationale']}")
Custom Assistant
Create a custom assistant with specific instructions:
from openai import OpenAI
from lrs.integration.openai_assistants import OpenAIAssistantLens
client = OpenAI(api_key="sk-...")
# Create assistant
assistant = client.beta.assistants.create(
name="Data Analyst",
instructions="""You are a data analysis assistant.
When given a task, propose 3-5 different strategies.
Consider both quick approaches and thorough analyses.""",
model="gpt-4-turbo-preview",
tools=[{"type": "code_interpreter"}]
)
# Wrap as LRS tool
assistant_lens = OpenAIAssistantLens(
client=client,
assistant_id=assistant.id,
temperature=0.7
)
# Use in policy generation
result = assistant_lens.get({
'query': 'Generate proposals for data analysis',
'precision': 0.5,
'available_tools': ['fetch', 'analyze', 'visualize']
})
Precision-Adaptive Temperature
Temperature automatically adjusts based on precision:
generator = OpenAIAssistantPolicyGenerator(client, model="gpt-4-turbo-preview")
# Low precision → High temperature (explore)
proposals_explore = generator.generate_proposals(
state={'goal': 'Task'},
precision=0.3 # Temperature ≈ 1.2
)
# High precision → Low temperature (exploit)
proposals_exploit = generator.generate_proposals(
state={'goal': 'Task'},
precision=0.8 # Temperature ≈ 0.5
)
The formula:
where γ is precision and T_base is the base temperature (default 0.7).
Using Built-in Assistant Tools
Code Interpreter
Enable code execution in proposals:
assistant = client.beta.assistants.create(
name="Code Analysis Agent",
model="gpt-4-turbo-preview",
tools=[{"type": "code_interpreter"}]
)
generator = OpenAIAssistantPolicyGenerator(
client=client,
assistant_id=assistant.id
)
# Assistant can now propose policies that use code execution
proposals = generator.generate_proposals(
state={'goal': 'Analyze CSV file', 'file_path': 'data.csv'},
precision=0.5
)
File Search
Enable file search capabilities:
# Upload files
file = client.files.create(
file=open("knowledge_base.pdf", "rb"),
purpose="assistants"
)
# Create assistant with file search
assistant = client.beta.assistants.create(
name="Research Assistant",
model="gpt-4-turbo-preview",
tools=[{"type": "file_search"}],
file_ids=[file.id]
)
# Assistant can now search uploaded files in proposals
Function Calling
Define functions for the assistant to use:
functions = [
{
"type": "function",
"function": {
"name": "search_database",
"description": "Search the customer database",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string"},
"limit": {"type": "integer"}
},
"required": ["query"]
}
}
}
]
assistant = client.beta.assistants.create(
name="Database Agent",
model="gpt-4-turbo-preview",
tools=functions
)
# Implement function
def search_database(query, limit=10):
# Your implementation
return results
# Use with LRS
generator = OpenAIAssistantPolicyGenerator(
client=client,
assistant_id=assistant.id
)
Complete Agent Example
Here’s a complete example with file analysis:
from openai import OpenAI
from lrs.integration.openai_assistants import create_openai_lrs_agent
from lrs.core.lens import ToolLens, ExecutionResult
from lrs.monitoring.tracker import LRSStateTracker
# Initialize
client = OpenAI(api_key="sk-...")
tracker = LRSStateTracker()
# Custom tool for saving results
class SaveResultsTool(ToolLens):
def __init__(self):
super().__init__("save_results", {}, {})
def get(self, state):
self.call_count += 1
results = state.get('analysis_results')
if not results:
self.failure_count += 1
return ExecutionResult(False, None, "No results", 0.9)
# Save to file
with open('results.json', 'w') as f:
json.dump(results, f)
return ExecutionResult(True, "Saved", None, 0.05)
def set(self, state, obs):
return {**state, 'saved': True}
# Create assistant
assistant = client.beta.assistants.create(
name="Data Analyst",
instructions="""Analyze data files and provide insights.
When proposing strategies, consider:
1. Quick exploratory analysis
2. Thorough statistical analysis
3. Visualization-focused analysis""",
model="gpt-4-turbo-preview",
tools=[{"type": "code_interpreter"}]
)
# Create LRS agent
agent = create_openai_lrs_agent(
client=client,
assistant_id=assistant.id,
tools=[SaveResultsTool()],
tracker=tracker,
preferences={
'success': 5.0,
'error': -3.0,
'step_cost': -0.2
}
)
# Upload file
file = client.files.create(
file=open("sales_data.csv", "rb"),
purpose="assistants"
)
# Run analysis
result = agent.run(
task=f"Analyze the sales data in file {file.id}",
max_iterations=15
)
# Review results
print(f"Steps: {len(result['tool_history'])}")
print(f"Adaptations: {result.get('adaptation_count', 0)}")
print(f"\nFinal precision: {result['precision']['execution']:.2f}")
Handling Long-Running Operations
Assistants can take time to respond. Handle this gracefully:
from lrs.integration.openai_assistants import OpenAIAssistantLens
assistant_lens = OpenAIAssistantLens(
client=client,
assistant_id=assistant.id,
max_wait=300, # Wait up to 5 minutes
poll_interval=2.0 # Check every 2 seconds
)
# LRS will:
# 1. Submit query to assistant
# 2. Poll for completion
# 3. Return high prediction error if timeout
# 4. Trigger adaptation if precision drops
Error Handling
Rate Limits
OpenAI has rate limits. LRS handles these automatically:
# When rate limited:
# - Assistant returns error
# - LRS records high prediction error (0.9)
# - Precision drops
# - Agent explores alternatives
# - Might wait and retry, or use different tools
from lrs.core.lens import ToolLens, ExecutionResult
class RateLimitAwareTool(ToolLens):
def get(self, state):
try:
result = openai_call(state)
return ExecutionResult(True, result, None, 0.1)
except openai.RateLimitError:
# Expected but bad
return ExecutionResult(False, None, "Rate limited", 0.7)
except Exception as e:
# Unexpected
return ExecutionResult(False, None, str(e), 0.95)
Timeouts
Handle assistant timeouts:
assistant_lens = OpenAIAssistantLens(
client=client,
assistant_id=assistant.id,
max_wait=120 # Timeout after 2 minutes
)
# If assistant doesn't respond:
# - Returns ExecutionResult with success=False
# - High prediction error (0.9)
# - Agent adapts and tries alternatives
Best Practices
1. Provide Clear Instructions
assistant = client.beta.assistants.create(
name="Research Assistant",
instructions="""You are a research assistant using Active Inference.
When proposing policies:
- Generate 3-5 diverse proposals
- Include exploration strategies (novel tools)
- Include exploitation strategies (reliable tools)
- Balance information gain vs reward
For each proposal, specify:
- Tool sequence
- Estimated success probability
- Expected information gain
- Potential failure modes""",
model="gpt-4-turbo-preview"
)
2. Monitor Performance
from lrs.monitoring.tracker import LRSStateTracker
tracker = LRSStateTracker()
agent = create_openai_lrs_agent(client, assistant_id, tracker=tracker)
# After execution
stats = tracker.get_tool_usage_stats()
# Check if assistant is generating good proposals
print(f"Assistant success rate: {stats['assistant']['success_rate']:.1%}")
3. Combine with Custom Tools
# Use assistant for policy generation
# Use custom tools for execution
agent = create_openai_lrs_agent(
client=client,
assistant_id=assistant.id,
tools=[
CustomCacheTool(),
CustomDatabaseTool(),
CustomAPITool()
]
)
# Assistant proposes, custom tools execute
# Best of both worlds!
4. Set Appropriate Timeouts
# Quick tasks
quick_assistant = OpenAIAssistantLens(
client, assistant_id, max_wait=30
)
# Complex analyses
analysis_assistant = OpenAIAssistantLens(
client, assistant_id, max_wait=300
)
Cost Optimization
Minimize Costs
# Use GPT-3.5 for simple tasks
cheap_generator = OpenAIAssistantPolicyGenerator(
client=client,
model="gpt-3.5-turbo", # Cheaper
registry=registry
)
# Use GPT-4 for complex tasks
smart_generator = OpenAIAssistantPolicyGenerator(
client=client,
model="gpt-4-turbo-preview", # More expensive but better
registry=registry
)
# Switch based on task complexity
if task_complexity < 0.5:
proposals = cheap_generator.generate_proposals(state, precision)
else:
proposals = smart_generator.generate_proposals(state, precision)
Cache Responses
from functools import lru_cache
@lru_cache(maxsize=100)
def cached_generate_proposals(state_hash, precision):
return generator.generate_proposals(state, precision)
# Use hash of state for caching
import hashlib
state_hash = hashlib.md5(str(state).encode()).hexdigest()
proposals = cached_generate_proposals(state_hash, precision)
Troubleshooting
Assistant Not Responding
Check:
# Verify assistant exists
assistant = client.beta.assistants.retrieve(assistant_id)
print(f"Assistant: {assistant.name}")
# Check status
run = client.beta.threads.runs.retrieve(thread_id, run_id)
print(f"Status: {run.status}")
Poor Proposals
Improve instructions:
# Update assistant instructions
client.beta.assistants.update(
assistant_id,
instructions="""More detailed instructions here..."""
)
High Costs
Monitor usage:
# Track token usage
from lrs.monitoring.structured_logging import create_logger_for_agent
logger = create_logger_for_agent("agent_1")
# Log costs
logger.log_custom({
'event': 'assistant_call',
'tokens': run.usage.total_tokens,
'cost_estimate': run.usage.total_tokens * 0.00001
})
Next Steps
Try the ../tutorials/05_llm_integration tutorial
Read about LangChain Integration
See AutoGPT Integration for research agents
Explore Production Deployment for scaling