IFX-trace-implementation / api /trace_implementation.md
Liss, Alex (NYC-HUG)
Add trace implementation and documentation; removed old files
0698457
# Freeplay Traces Implementation Plan
## Overview
This document outlines the implementation plan for integrating Freeplay Traces into the existing Huge League Soccer application. Traces provide enhanced observability by grouping LLM interactions within a session, allowing us to track input questions, LLM responses, and associated metadata.
## Current Architecture
### Existing Freeplay Integration Points
1. **Session Management** (`api/server_gradio.py`)
- `AppState.ensure_sessions()` - Creates Freeplay session on first user interaction
- Session ID preserved across state changes
2. **Prompt Management** (`api/workflows/base.py`)
- `call_model()` - Retrieves persona-specific prompts via `get_prompt_by_persona()`
- Uses Freeplay prompt templates (casual_fan_prompt, super_fan_prompt)
3. **Session Recording** (`api/workflows/base.py`)
- `should_continue()` - Records final LLM responses to Freeplay session
- Uses `record_session()` method
## Proposed Traces Implementation
### AppState Enhancement
The `AppState` class will be enhanced to store the actual Freeplay session object, allowing direct access to `session.create_trace()` as shown in the original documentation.
### Modified Methods
```python
# api/utils/freeplay_helpers.py - Modified method
def record_session(self, state, end: Optional[float] = time.time(),
formatted_prompt: Optional[FormattedPrompt] = None,
prompt_vars: Optional[dict] = None,
trace_info: Optional[TraceInfo] = None): # NEW PARAMETER
# ... existing code ...
payload = RecordPayload(
# ... existing fields ...
trace_info=trace_info # NEW FIELD
)
```
## Implementation Flow
### 1. AppState Enhancement
**Location:** `api/server_gradio.py` - `AppState` class
```python
class AppState(BaseModel):
# ... existing fields ...
freeplay_session_id: str = ""
freeplay_session: Optional[Any] = None # NEW: Store the actual session object
def ensure_sessions(self):
if not self.zep_session_id:
self.zep_session_id = ZepClient() \
.get_or_create_user(self.email, self.first_name, self.last_name) \
.create_session() \
.session_id
if not self.freeplay_session_id:
freeplay_client = FreeplayClient()
self.freeplay_session = freeplay_client.create_session() # Store session object
self.freeplay_session_id = self.freeplay_session.session_id
```
### 2. User Input & Trace Creation
**Location:** `api/server_gradio.py` - `submit_helper()`
```python
def submit_helper(state, handler, user_query):
state.ensure_sessions() # Freeplay session already exists
# Create trace directly on the session object
trace_info = state.freeplay_session.create_trace(
input=user_query, # optional metadata not included
)
# Pass trace_info to workflow
workflow_bundle, workflow_state = build_workflow_with_state(
handler=handler,
zep_session_id=state.zep_session_id,
freeplay_session_id=state.freeplay_session_id,
email=state.email,
first_name=state.first_name,
last_name=state.last_name,
persona=state.persona,
messages=state.history,
trace_info=trace_info, # NEW: Pass trace_info to workflow
)
```
### 3. Workflow State Enhancement
**Location:** `api/workflows/base.py` - `AgentState`
```python
class AgentState(TypedDict):
# ... existing fields ...
trace_info: Optional[TraceInfo] = None # NEW
```
### 4. Workflow Builder Enhancement
**Location:** `api/workflows/base.py` - `build_workflow_with_state()`
```python
def build_workflow_with_state(handler: AsyncCallbackHandler,
zep_session_id: Optional[str] = None,
freeplay_session_id: Optional[str] = None,
email: Optional[str] = None,
first_name: Optional[str] = None,
last_name: Optional[str] = None,
persona: Optional[str] = None,
messages: Optional[List[BaseMessage]] = None,
trace_info: Optional[TraceInfo] = None) -> Tuple[WorkflowBundle, AgentState]: # NEW PARAMETER
"""
Utility to build workflow and initial state in one step.
"""
bundle = build_workflow(handler)
state = {
"zep_session_id": zep_session_id,
"freeplay_session_id": freeplay_session_id,
"email": email,
"first_name": first_name,
"last_name": last_name,
"persona": persona,
"messages": messages or [],
"start_time": time.time(),
"zep_memory": None,
"trace_info": trace_info, # NEW: Populate trace_info in AgentState
}
return bundle, state
```
### 5. LLM Processing with Trace Association
**Location:** `api/workflows/base.py` - `call_model()`
```python
async def call_model(state: AgentState,
handler: AsyncCallbackHandler,
zep_client: ZepClient,
freeplay_client: FreeplayClient) -> dict:
# ... existing prompt and LLM logic ...
# Record trace output with LLM response
if state.get("trace_info"):
final_response = response.content if hasattr(response, 'content') else str(response)
state["trace_info"].record_output(
project_id=FREEPLAY_PROJECT_ID,
output=final_response
)
return {'messages': [response], 'zep_memory': memory}
```
### 6. Session Recording with Trace
**Location:** `api/workflows/base.py` - `should_continue()`
```python
async def should_continue(state: AgentState,
handler: AsyncCallbackHandler,
zep_client: ZepClient,
freeplay_client: FreeplayClient) -> str:
# ... existing logic ...
if 'tool_calls' not in last_message.additional_kwargs:
# Record session with trace association
freeplay_client.record_session(state, trace_info=state.get("trace_info"))
return 'end'
return 'continue'
```
## Data Flow Diagram
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ User Input β”‚ β”‚ submit_helper β”‚ β”‚ AppState β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ "Tell me about │───▢│ 1. ensure_sessions│───▢│ freeplay_sessionβ”‚
β”‚ Ryan Martinez" β”‚ β”‚ 2. create_trace() β”‚ β”‚ .create_trace() β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ 3. pass trace_infoβ”‚ β”‚ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ β”‚
β–Ό β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ build_workflow_ β”‚ β”‚ Trace Info β”‚
β”‚ with_state() β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ - trace_id β”‚
β”‚ - trace_info β”‚ β”‚ - input β”‚
β”‚ - user_query β”‚ β”‚ - metadata β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ AgentState β”‚
β”‚ β”‚
β”‚ - trace_info β”‚
β”‚ - messages β”‚
β”‚ - persona β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Workflow β”‚
β”‚ Execution β”‚
β”‚ β”‚
β”‚ call_model() β”‚
β”‚ - get_prompt() β”‚
β”‚ - LLM call β”‚
β”‚ - record_output()β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ should_continue()β”‚
β”‚ β”‚
β”‚ record_session() β”‚
β”‚ with trace_info β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Freeplay Session β”‚
β”‚ Recording β”‚
β”‚ β”‚
β”‚ - Session ID β”‚
β”‚ - Trace Info β”‚
β”‚ - Input/Output β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
## Trace Lifecycle
### 1. **Creation Phase**
- **Trigger:** User submits question
- **Location:** `submit_helper()`
- **Action:** Create trace with user input and metadata
- **Output:** `TraceInfo` object with `trace_id`
### 2. **Association Phase**
- **Trigger:** Workflow initialization
- **Location:** `build_workflow_with_state()`
- **Action:** Pass `trace_info` to workflow state
- **Output:** `AgentState` with trace context
### 3. **Processing Phase**
- **Trigger:** LLM interaction
- **Location:** `call_model()`
- **Action:** Record LLM output to trace
- **Output:** Trace with input/output pair
### 4. **Recording Phase**
- **Trigger:** Workflow completion
- **Location:** `should_continue()`
- **Action:** Associate trace with session recording
- **Output:** Complete session with trace linkage
## Benefits
### Enhanced Observability
- **Input/Output Tracking:** Complete visibility of user questions and LLM responses
- **Metadata Association:** Persona, user info, and interaction context
- **Performance Metrics:** Response times, tool usage, and evaluation results
### Debugging & Analysis
- **Trace Isolation:** Individual interactions can be analyzed separately
- **Session Context:** Traces maintain session-level context
- **Evaluation Support:** Built-in support for feedback and evaluation metrics
### Backward Compatibility
- **Optional Implementation:** Traces are opt-in, existing functionality unchanged
- **Graceful Degradation:** System works without traces if disabled
- **Incremental Rollout:** Can be enabled per user or session
## Implementation Phases
### Phase 1: AppState Enhancement
1. Add `freeplay_session` property to `AppState` class
2. Modify `ensure_sessions()` to store session object
3. Test session object storage and retrieval
### Phase 2: Workflow Integration
1. Update `AgentState` to include `trace_info` field
2. Modify `build_workflow_with_state()` to accept `trace_info` parameter
3. Update `call_model()` to record trace outputs
4. Update `should_continue()` to associate traces with sessions
### Phase 3: Server Integration
1. Update `submit_helper()` to create traces using session object
2. Pass `trace_info` through workflow initialization
3. Test complete trace lifecycle
### Phase 4: Session Recording Enhancement
1. Modify `record_session()` to accept `trace_info` parameter
2. Update `RecordPayload` to include trace information
3. Test session recording with trace association
### Phase 5: Testing & Validation
1. Unit tests for trace creation and recording
2. Integration tests for workflow trace integration
3. End-to-end tests for complete trace lifecycle
4. Performance impact assessment
## Risk Mitigation
### High Risk Areas
1. **Session State Management**
- **Risk:** Breaking existing session flow
- **Mitigation:** Optional trace parameters, backward compatibility
2. **Workflow State Changes**
- **Risk:** Breaking existing state structure
- **Mitigation:** Optional fields with defaults, thorough testing
### Medium Risk Areas
1. **Performance Impact**
- **Risk:** Slowing down workflow execution
- **Mitigation:** Lazy trace creation, optional features
2. **Data Consistency**
- **Risk:** Trace/recording mismatches
- **Mitigation:** Validation and error handling
## Success Criteria
1. **Functionality:** Traces created and recorded for all user interactions
2. **Performance:** No measurable impact on workflow execution time
3. **Compatibility:** All existing functionality continues to work
4. **Observability:** Complete trace data available in Freeplay dashboard
5. **Reliability:** Graceful handling of trace creation/recording failures
## Next Steps
1. **User Approval:** Review and approve implementation plan
2. **Phase 1 Implementation:** Begin with core infrastructure
3. **Testing Strategy:** Validate each phase before proceeding
4. **Documentation:** Update API documentation with trace features
5. **Monitoring:** Implement trace-specific logging and metrics