Bilan v0.4.1 introduces Turn ID Unification - a significant improvement that replaces the confusing dual-ID system with industry-standard event correlation. This follows proven patterns from Amplitude, Mixpanel, and other major analytics platforms.
- Before: Manual
promptIdcreation separate fromturn_id - After: Single
turnIdreturned bytrackTurn()for all related events
- Before: Unique dual-ID approach unlike other analytics platforms
- After: Follows Amplitude/Mixpanel event correlation patterns
- Before: No built-in correlation between turns and votes
- After: Automatic turn-to-vote correlation with optional context
- Before: Fragmented data requiring manual correlation
- After: Rich relationship data supporting advanced analytics
// v0.4.0 - Returns AI response directly
const response = await trackTurn(prompt, aiCall)
// v0.4.1 - Returns object with result + turnId
const { result, turnId } = await trackTurn(prompt, aiCall)// OLD v0.4.0 code:
const emailResponse = await trackTurn(
'Write a professional email',
() => openai.chat.completions.create({...})
)
console.log(emailResponse.choices[0].message.content)
// NEW v0.4.1 code:
const { result: emailResponse, turnId } = await trackTurn(
'Write a professional email',
() => openai.chat.completions.create({...})
)
console.log(emailResponse.choices[0].message.content)
// turnId is now available for feedback correlation// v0.4.0 - Manual promptId creation
await vote(createPromptId('manual-id'), 1, 'Good')
// v0.4.1 - Use turnId from trackTurn
await vote(turnId, 1, 'Good')// OLD v0.4.0 pattern:
const response = await trackTurn('Help with code', aiCall)
// ... later in your code ...
await vote(createPromptId('code-help-123'), 1, 'Helpful!')
// NEW v0.4.1 pattern:
const { result: response, turnId } = await trackTurn('Help with code', aiCall)
// ... later in your code ...
await vote(turnId, 1, 'Helpful!') // Automatic correlation!// β These exports are removed in v0.4.1:
import { createPromptId, PromptId } from '@mocksi/bilan-sdk'
// β
Use turnId from trackTurn instead:
const { result, turnId } = await trackTurn(...)npm install @mocksi/bilan-sdk@^0.4.1Find all trackTurn() calls and destructure the return value:
// Search for this pattern:
const response = await trackTurn(
// Replace with:
const { result: response, turnId } = await trackTurn(Find all vote() calls and replace promptId with turnId:
// Search for this pattern:
await vote(createPromptId('...'), value, comment)
// Replace with turnId from trackTurn:
await vote(turnId, value, comment)// Remove these imports:
import { createPromptId, PromptId } from '@mocksi/bilan-sdk'
// Keep these imports (unchanged):
import { init, trackTurn, vote, createUserId } from '@mocksi/bilan-sdk'// β v0.4.0 - Dual ID system
const response = await trackTurn(
'Generate a summary',
() => openai.chat.completions.create({...})
)
await vote(createPromptId('summary-123'), 1, 'Great summary!')
// β
v0.4.1 - Unified ID system
const { result: response, turnId } = await trackTurn(
'Generate a summary',
() => openai.chat.completions.create({...})
)
await vote(turnId, 1, 'Great summary!')// β v0.4.0 - Manual correlation
const stream = await trackTurn(
'Write a story',
() => openai.chat.completions.create({
model: 'gpt-4',
messages: [...],
stream: true
})
)
// Manual tracking required for feedback
const manualId = createPromptId('story-' + Date.now())
await vote(manualId, 1, 'Engaging story!')
// β
v0.4.1 - Automatic correlation
const { result: stream, turnId } = await trackTurn(
'Write a story',
() => openai.chat.completions.create({
model: 'gpt-4',
messages: [...],
stream: true
})
)
// Automatic correlation with turnId
await vote(turnId, 1, 'Engaging story!')// β v0.4.0 - Limited context tracking
const response = await trackTurn(
'Code review feedback',
() => callAI(prompt),
{ context: 'code-review' }
)
// β
v0.4.1 - Rich context relationships
const { result: response, turnId } = await trackTurn(
'Code review feedback',
() => callAI(prompt),
{
journey_id: 'code-review-workflow',
conversation_id: 'conv_123',
turn_sequence: 2
}
)
await vote(turnId, 1, 'Helpful review!')// β v0.4.0 - Separate error tracking
try {
const response = await trackTurn('Analyze data', aiCall)
await vote(createPromptId('analysis'), 1, 'Good analysis')
} catch (error) {
await vote(createPromptId('analysis'), -1, 'Failed to analyze')
}
// β
v0.4.1 - Correlated error tracking
let turnId: string
try {
const { result: response, turnId: id } = await trackTurn('Analyze data', aiCall)
turnId = id
await vote(turnId, 1, 'Good analysis')
} catch (error) {
if (turnId) {
await vote(turnId, -1, 'Failed to analyze')
}
}After migration, verify:
- Compilation: TypeScript compilation succeeds without errors
- Functionality: All
trackTurn()calls work with destructured return - Correlation: Votes are properly linked to turns (check dashboard)
- Context: Optional context fields are captured correctly
- Analytics: Turn-to-vote correlation appears in analytics
- Performance: No regression in response times
- Error Handling: Error scenarios still work correctly
Property 'choices' does not exist on type '{ result: any; turnId: string; }'Solution: Destructure the return value properly
// Wrong:
const response = await trackTurn(...)
console.log(response.choices)
// Correct:
const { result: response } = await trackTurn(...)
console.log(response.choices)Cannot find name 'createPromptId'Solution: Use turnId from trackTurn instead
// Wrong:
await vote(createPromptId('manual'), 1)
// Correct:
const { result, turnId } = await trackTurn(...)
await vote(turnId, 1)Response is undefined after trackTurn callSolution: Access the result property
// Wrong:
const response = await trackTurn(...)
// Correct:
const { result: response, turnId } = await trackTurn(...)- Cleaner Code: No manual ID generation
- Automatic Correlation: System handles event relationships
- Industry Familiarity: Same patterns as Amplitude/Mixpanel
- Type Safety: Better TypeScript integration
- Direct Turn-Vote Correlation: See which AI responses users liked
- Context Relationships: Optional journey/conversation tracking
- Enhanced Insights: Richer data for analytics queries
- Performance Gains: Optimized correlation queries
- Consistent IDs: System-generated IDs prevent duplicates
- Relationship Tracking: Proper foreign key relationships
- Migration Safety: Existing data automatically migrated
- Rollback Support: Can revert if needed
- Existing vote events are automatically migrated
promptIdfields mapped toturn_idwhere possible- No manual data migration required
- Zero downtime migration process
// v0.4.1 includes migration validation
import { validateMigration } from '@mocksi/bilan-sdk/migration'
const result = await validateMigration()
console.log('Migration status:', result.isValid)
console.log('Migrated events:', result.migratedCount)const { result, turnId } = await trackTurn(
'Review PR #123',
() => callAI(prompt),
{
journey_id: 'code-review',
conversation_id: 'pr-123-discussion',
turn_sequence: 3,
customData: { prId: 123, reviewer: 'alice' }
}
)The new schema supports (but doesn't require):
- Frustration detection within conversations
- Journey completion analysis
- Cross-context performance insights
- Multi-turn conversation analysis
- Migration Script: Automated code transformation
- Validation Tool: Check migration completeness
- Rollback Plan: Revert if issues arise
- Documentation: Updated examples and guides
- GitHub Issues: Report migration problems
- Discord Community: Real-time migration support
- Migration Guide: This document with common patterns
The v0.4.1 migration brings Bilan in line with industry standards while dramatically improving both developer experience and analytics capabilities. The unified turn ID system provides the foundation for advanced AI analytics features while maintaining the simplicity that makes Bilan unique.