LLM Guide
Stick this in your robot's context window.
This guide provides a comprehensive overview of the vCon (Virtual Conversation) Python library, designed specifically for Large Language Models (LLMs) that need to generate or modify code using this library.
Overview
The vCon library is a Python implementation of the vCon 0.3.0 specification for structuring, managing, and manipulating conversation data in a standardized format. It enables the creation, validation, and manipulation of digital representations of conversations with rich metadata, supporting all modern conversation features including multimedia content, security, and extensibility.
Key Concepts
vCon Container: The primary object that holds all conversation data
Parties: Participants in a conversation (callers, agents, bots) with contact information
Dialogs: Individual messages or segments of the conversation (text, audio, video, etc.)
Attachments: Additional files or data associated with the conversation
Analysis: Results from processing the conversation (sentiment analysis, transcription, etc.)
Extensions: Optional features that extend the base vCon functionality
Digital Signatures: Cryptographic verification of vCon integrity
Civic Addresses: Location information for parties using GEOPRIV standard
Party History: Event tracking for multi-party conversations
Installation
# Basic installation
pip install vcon
# With image processing support (Pillow, PyPDF)
pip install vcon[image]
# From source
git clone https://github.com/vcon-dev/vcon-lib.git
cd vcon-lib
pip install -e .
Requirements
Python 3.12+
Core dependencies: authlib, uuid6, requests, pydash, python-dateutil
Optional: mutagen (audio metadata), ffmpeg (video processing), Pillow (image processing), PyPDF (PDF processing)
Core Classes and Usage Patterns
1. Vcon Class
The main container for all conversation data.
Creating a vCon
from vcon import Vcon
# Create a new empty vCon
vcon = Vcon.build_new()
# Create from existing JSON
vcon = Vcon.build_from_json(json_string)
# Load from file
vcon = Vcon.load_from_file("conversation.json")
# Load from URL
vcon = Vcon.load_from_url("https://example.com/conversation.json")
# Generic load (detects if path or URL)
vcon = Vcon.load("conversation.json") # or URL
Saving and Exporting
# Save to file
vcon.save_to_file("conversation.json")
# Convert to JSON string
json_str = vcon.to_json() # or vcon.dumps()
# Convert to dictionary
vcon_dict = vcon.to_dict()
# Post to URL with optional headers
response = vcon.post_to_url(
'https://api.example.com/vcons',
headers={'x-api-token': 'your-token-here'}
)
Properties
# Access properties
uuid = vcon.uuid
version = vcon.vcon
created_at = vcon.created_at
updated_at = vcon.updated_at
parties_list = vcon.parties
dialog_list = vcon.dialog
attachments_list = vcon.attachments
analysis_list = vcon.analysis
2. Party Class
Represents a participant in the conversation.
from vcon.party import Party
# Create a party
caller = Party(
tel="+1234567890",
name="Alice Smith",
role="caller",
mailto="[email protected]"
)
# Add to vCon
vcon.add_party(caller)
# Find a party by an attribute
party_index = vcon.find_party_index("name", "Alice Smith") # Returns index (0-based)
Party Attributes
Core Contact Information:
tel
: Telephone number (e.g., "+1234567890")name
: Display name (e.g., "Alice Smith")role
: Role in conversation ("caller", "agent", "bot", etc.)mailto
: Email address (e.g., "[email protected]")
Advanced Contact Methods (vCon 0.3.0):
sip
: SIP URI for VoIP communication (e.g., "sip:[email protected]")did
: Decentralized Identifier for blockchain-based identityjCard
: vCard format contact information (RFC 7095)timezone
: Party's timezone (e.g., "America/New_York")
Location and Validation:
civicaddress
: Civic address using CivicAddress class (GEOPRIV format)gmlpos
: GML position coordinatesvalidation
: Validation statusstir
: STIR verification for secure telephony
Metadata:
uuid
: Unique identifier for the partycontact_list
: Reference to contact listmeta
: Additional metadata dictionaryCustom attributes can be added via kwargs
3. Dialog Class
Represents a message or segment in the conversation.
from vcon.dialog import Dialog
from datetime import datetime, timezone
# Create a text dialog
text_dialog = Dialog(
type="text",
start=datetime.now(timezone.utc).isoformat(),
parties=[0, 1], # Indices of parties involved
originator=0, # Index of the party that sent the message
mimetype="text/plain",
body="Hello, I need help with my account."
)
# Add to vCon
vcon.add_dialog(text_dialog)
# Create an audio dialog
audio_dialog = Dialog(
type="audio",
start=datetime.now(timezone.utc).isoformat(),
parties=[0, 1],
originator=0,
mimetype="audio/mp3",
body=base64_encoded_audio,
encoding="base64",
filename="recording.mp3"
)
vcon.add_dialog(audio_dialog)
# Find a dialog by property
found_dialog = vcon.find_dialog("type", "text")
Special Dialog Types
# Add a transfer dialog
vcon.add_transfer_dialog(
start=datetime.now(timezone.utc).isoformat(),
transfer_data={
"reason": "Call forwarded",
"from": "+1234567890",
"to": "+1987654321"
},
parties=[0, 1]
)
# Add an incomplete dialog (for failed conversations)
vcon.add_incomplete_dialog(
start=datetime.now(timezone.utc).isoformat(),
disposition="NO_ANSWER",
details={"ringDuration": 45000},
parties=[0, 1]
)
Dialog Type Methods
# Check dialog type
is_text = dialog.is_text()
is_recording = dialog.is_recording()
is_transfer = dialog.is_transfer()
is_incomplete = dialog.is_incomplete()
is_audio = dialog.is_audio()
is_video = dialog.is_video()
is_email = dialog.is_email()
Dialog Types and MIME Types
Valid Dialog Types:
"text"
: Text-based communication (chat, SMS, email)"recording"
: Audio/video recording"transfer"
: Call transfer operation"incomplete"
: Failed or incomplete conversation setup"audio"
: Audio content"video"
: Video content
Supported MIME Types:
Text:
text/plain
Audio:
audio/x-wav
,audio/wav
,audio/wave
audio/mpeg
,audio/mp3
,audio/x-mp3
audio/x-mp4
,audio/ogg
,audio/webm
audio/x-m4a
,audio/aac
Video:
video/x-mp4
,video/mp4
,video/ogg
video/quicktime
,video/webm
video/x-msvideo
,video/x-matroska
video/mpeg
,video/x-flv
,video/3gpp
,video/x-m4v
Other:
multipart/mixed
message/rfc822
(for email)application/json
(for signaling data)image/jpeg
,image/tiff
,application/pdf
4. Working with Tags
Tags are key-value pairs for simple metadata.
# Add tags
vcon.add_tag("customer_id", "12345")
vcon.add_tag("interaction_id", "INT-001")
# Get tag value
value = vcon.get_tag("customer_id") # Returns "12345"
# Get all tags
all_tags = vcon.tags # Returns the tags attachment dictionary
5. Working with Attachments
Attachments are arbitrary data associated with the conversation.
# Add an attachment
vcon.add_attachment(
type="transcript",
body="Conversation transcript content...",
encoding="none"
)
# Add a base64-encoded attachment
vcon.add_attachment(
type="recording",
body=base64_encoded_content,
encoding="base64url"
)
# Find an attachment
attachment = vcon.find_attachment_by_type("transcript")
6. Working with Analysis
Analysis entries represent insights derived from dialog.
# Add analysis
vcon.add_analysis(
type="sentiment",
dialog=[0], # Index or indices of dialogs analyzed
vendor="AnalysisCompany",
body={"sentiment": "positive", "score": 0.8},
encoding="json"
)
# Find analysis
analysis = vcon.find_analysis_by_type("sentiment")
7. Extensions and Must-Support (vCon 0.3.0)
Extensions allow vCons to declare optional features they use, while must-support indicates required features.
# Add extensions used in this vCon
vcon.add_extension("video")
vcon.add_extension("encryption")
vcon.add_extension("sentiment_analysis")
# Add extensions that must be supported by consumers
vcon.add_must_support("encryption")
vcon.add_must_support("video")
# Get extensions
extensions = vcon.get_extensions() # ['video', 'encryption', 'sentiment_analysis']
must_support = vcon.get_must_support() # ['encryption', 'video']
# Remove extensions
vcon.remove_extension("sentiment_analysis")
vcon.remove_must_support("video")
8. Civic Address Support (vCon 0.3.0)
Civic addresses provide location information for parties using the GEOPRIV standard.
from vcon.civic_address import CivicAddress
# Create civic address
address = CivicAddress(
country="US",
a1="CA", # State
a3="San Francisco", # City
sts="Market Street", # Street
hno="123", # House number
pc="94102" # Postal code
)
# Add to party
party = Party(
name="Jane Doe",
tel="+1555123456",
civicaddress=address
)
# Convert to dictionary
address_dict = address.to_dict()
9. Party History Events (vCon 0.3.0)
Track when parties join, leave, or change state during conversations.
from vcon.party import PartyHistory
from datetime import datetime
# Create party history events
history = [
PartyHistory(0, "join", datetime.now()), # Party 0 joins
PartyHistory(1, "join", datetime.now()), # Party 1 joins
PartyHistory(0, "hold", datetime.now()), # Party 0 on hold
PartyHistory(0, "unhold", datetime.now()), # Party 0 off hold
PartyHistory(1, "drop", datetime.now()) # Party 1 drops
]
# Add to dialog
dialog = Dialog(
type="recording",
start=datetime.now(),
parties=[0, 1],
party_history=history
)
# Valid event types: "join", "drop", "hold", "unhold", "mute", "unmute"
10. Advanced Dialog Features (vCon 0.3.0)
New dialog fields for enhanced functionality.
# Dialog with session tracking and content hashing
dialog = Dialog(
type="text",
start=datetime.now(),
parties=[0, 1],
originator=0,
body="Hello, this is a test message!",
session_id="session-12345",
content_hash="c8d3d67f662a787e96e74ccb0a77803138c0f13495a186ccbde495c57c385608",
application="chat-app",
message_id="<[email protected]>"
)
# Video dialog with metadata
video_dialog = Dialog(
type="video",
start=datetime.now(),
parties=[0, 1],
mimetype="video/mp4",
resolution="1920x1080",
frame_rate=30.0,
codec="H.264",
bitrate=5000000,
filename="recording.mp4"
)
# Incomplete dialog with disposition
incomplete_dialog = Dialog(
type="incomplete",
start=datetime.now(),
parties=[0],
disposition="no-answer" # Valid: no-answer, congestion, failed, busy, hung-up, voicemail-no-message
)
11. Security and Validation
Signing and Verification
# Generate a key pair
private_key, public_key = Vcon.generate_key_pair()
# Sign the vCon
vcon.sign(private_key)
# Verify the signature
is_valid = vcon.verify(public_key)
Validation
# Validate a vCon object
is_valid, errors = vcon.is_valid()
if not is_valid:
print("Validation errors:", errors)
# Validate a file
is_valid, errors = Vcon.validate_file("conversation.json")
# Validate a JSON string
is_valid, errors = Vcon.validate_json(json_string)
Common Patterns and Best Practices
1. Creating a Complete Conversation
from vcon import Vcon
from vcon.party import Party
from vcon.dialog import Dialog
from datetime import datetime, timezone
# Create a new vCon
vcon = Vcon.build_new()
# Add participants
caller = Party(tel="+1234567890", name="Alice", role="caller")
agent = Party(tel="+1987654321", name="Bob", role="agent")
vcon.add_party(caller)
vcon.add_party(agent)
# Add conversation dialogs in sequence
vcon.add_dialog(Dialog(
type="text",
start=datetime.now(timezone.utc).isoformat(),
parties=[0, 1],
originator=0, # Caller
mimetype="text/plain",
body="Hello, I need help with my account."
))
vcon.add_dialog(Dialog(
type="text",
start=datetime.now(timezone.utc).isoformat(),
parties=[0, 1],
originator=1, # Agent
mimetype="text/plain",
body="I'd be happy to help. Can you provide your account number?"
))
# Add metadata
vcon.add_tag("customer_id", "12345")
vcon.add_tag("interaction_id", "INT-001")
# Validate and save
is_valid, errors = vcon.is_valid()
if is_valid:
vcon.save_to_file("conversation.json")
else:
print("Validation errors:", errors)
2. Working with Audio Content
import base64
# Reading an audio file and adding it to a dialog
with open("recording.mp3", "rb") as f:
audio_data = f.read()
audio_base64 = base64.b64encode(audio_data).decode("utf-8")
audio_dialog = Dialog(
type="audio",
start=datetime.now(timezone.utc).isoformat(),
parties=[0, 1],
originator=0,
mimetype="audio/mp3",
body=audio_base64,
encoding="base64",
filename="recording.mp3"
)
vcon.add_dialog(audio_dialog)
3. External vs Inline Content
# External content (referenced by URL)
external_dialog = Dialog(
type="recording",
start=datetime.now(timezone.utc).isoformat(),
parties=[0, 1],
url="https://example.com/recordings/call123.mp3",
mimetype="audio/mp3"
)
# Check if dialog refers to external content
if external_dialog.is_external_data():
# Convert to inline data
external_dialog.to_inline_data()
# Check if dialog contains inline data
if dialog.is_inline_data():
print("Dialog contains embedded content")
4. Video Content Handling
# Add video data with metadata
video_dialog = Dialog(
type="video",
start=datetime.now(),
parties=[0, 1],
mimetype="video/mp4",
resolution="1920x1080",
frame_rate=30.0,
codec="H.264"
)
# Add video data (inline or external)
video_dialog.add_video_data(
video_data=binary_video_data, # or URL string
filename="recording.mp4",
mimetype="video/mp4",
inline=True, # False for external reference
metadata={"duration": 120, "quality": "high"}
)
# Extract video metadata using FFmpeg
metadata = video_dialog.extract_video_metadata()
# Generate thumbnail
thumbnail_data = video_dialog.generate_thumbnail(
timestamp=10.0, # Time in seconds
width=320,
height=240,
quality=90
)
# Transcode video to different format
video_dialog.transcode_video(
target_format="webm",
codec="vp9",
bit_rate=2000000,
width=1280,
height=720
)
5. Image Content Handling
# Add image data from file
image_dialog = Dialog(
type="text", # Can be any type
start=datetime.now(),
parties=[0, 1]
)
# Add image from file
image_dialog.add_image_data(
image_path="screenshot.png",
mimetype="image/jpeg" # Optional, auto-detected if not provided
)
# Generate thumbnail
thumbnail_b64 = image_dialog.generate_thumbnail(max_size=(200, 200))
# Check if dialog has image content
if image_dialog.is_image():
print("Dialog contains image content")
# Check for PDF content
if image_dialog.is_pdf():
print("Dialog contains PDF content")
6. Content Hashing and Integrity
# Calculate content hash
content_hash = dialog.calculate_content_hash("sha256")
# Set content hash for external files
dialog.set_content_hash(content_hash)
# Verify content integrity
is_valid = dialog.verify_content_hash(expected_hash, "sha256")
# Check if external data has changed
if dialog.is_external_data_changed():
print("External content has been modified")
Error Handling
try:
vcon = Vcon.load_from_file("conversation.json")
is_valid, errors = vcon.is_valid()
if not is_valid:
print("Validation errors:", errors)
except FileNotFoundError:
print("File not found")
except json.JSONDecodeError:
print("Invalid JSON format")
except Exception as e:
print(f"Error: {str(e)}")
Working with Property Handling Modes
The Vcon constructor accepts a property_handling
parameter to control how non-standard properties are handled:
# Default mode: keep non-standard properties
vcon = Vcon(vcon_dict) # or Vcon(vcon_dict, property_handling="default")
# Strict mode: remove non-standard properties
vcon = Vcon(vcon_dict, property_handling="strict")
# Meta mode: move non-standard properties to meta object
vcon = Vcon(vcon_dict, property_handling="meta")
LLM-Specific Patterns and Best Practices
1. Code Generation Templates
When generating vCon code, use these templates as starting points:
Basic Conversation Template
from vcon import Vcon
from vcon.party import Party
from vcon.dialog import Dialog
from datetime import datetime
def create_basic_conversation():
# Create vCon
vcon = Vcon.build_new()
# Add parties
caller = Party(tel="+1234567890", name="Caller", role="caller")
agent = Party(tel="+1987654321", name="Agent", role="agent")
vcon.add_party(caller)
vcon.add_party(agent)
# Add conversation
vcon.add_dialog(Dialog(
type="text",
start=datetime.now().isoformat(),
parties=[0, 1],
originator=0,
body="Hello, I need help."
))
return vcon
Multimedia Conversation Template
def create_multimedia_conversation():
vcon = Vcon.build_new()
# Add parties with enhanced contact info
caller = Party(
tel="+1234567890",
name="Alice",
role="caller",
mailto="[email protected]",
timezone="America/New_York"
)
agent = Party(
tel="+1987654321",
name="Bob",
role="agent",
sip="sip:[email protected]"
)
vcon.add_party(caller)
vcon.add_party(agent)
# Add text dialog
vcon.add_dialog(Dialog(
type="text",
start=datetime.now().isoformat(),
parties=[0, 1],
originator=0,
body="Hello, I need help with my account."
))
# Add audio dialog
vcon.add_dialog(Dialog(
type="recording",
start=datetime.now().isoformat(),
parties=[0, 1],
mimetype="audio/mp3",
filename="conversation.mp3"
))
# Add analysis
vcon.add_analysis(
type="sentiment",
dialog=[0, 1],
vendor="SentimentAnalyzer",
body={"sentiment": "positive", "confidence": 0.85},
encoding="json"
)
return vcon
2. Common LLM Tasks
Converting Chat History to vCon
def chat_to_vcon(chat_messages, participants):
vcon = Vcon.build_new()
# Add participants as parties
party_map = {}
for i, participant in enumerate(participants):
party = Party(
name=participant.get("name", f"User {i}"),
role=participant.get("role", "participant")
)
vcon.add_party(party)
party_map[participant["id"]] = i
# Add messages as dialogs
for message in chat_messages:
vcon.add_dialog(Dialog(
type="text",
start=message["timestamp"],
parties=[party_map[message["sender_id"]]],
originator=party_map[message["sender_id"]],
body=message["content"]
))
return vcon
Adding AI Analysis to vCon
def add_ai_analysis(vcon, analysis_type, results, dialog_indices=None):
if dialog_indices is None:
dialog_indices = list(range(len(vcon.dialog)))
vcon.add_analysis(
type=analysis_type,
dialog=dialog_indices,
vendor="AI-Analyzer",
body=results,
encoding="json"
)
# Add extension if using AI features
vcon.add_extension("ai_analysis")
Extracting Conversation Data
def extract_conversation_data(vcon):
data = {
"uuid": vcon.uuid,
"created_at": vcon.created_at,
"parties": [],
"dialogs": [],
"analysis": []
}
# Extract parties
for party in vcon.parties:
data["parties"].append({
"name": getattr(party, "name", None),
"role": getattr(party, "role", None),
"tel": getattr(party, "tel", None)
})
# Extract dialogs
for dialog in vcon.dialog:
data["dialogs"].append({
"type": dialog.get("type"),
"start": dialog.get("start"),
"body": dialog.get("body", "")[:100] + "..." if len(dialog.get("body", "")) > 100 else dialog.get("body", ""),
"parties": dialog.get("parties", [])
})
# Extract analysis
for analysis in vcon.analysis:
data["analysis"].append({
"type": analysis.get("type"),
"vendor": analysis.get("vendor"),
"dialog_count": len(analysis.get("dialog", []))
})
return data
3. Error Handling Patterns
def safe_vcon_operation(operation_func, *args, **kwargs):
"""Safely execute vCon operations with proper error handling."""
try:
return operation_func(*args, **kwargs)
except ValueError as e:
return {"error": f"Validation error: {str(e)}", "success": False}
except FileNotFoundError as e:
return {"error": f"File not found: {str(e)}", "success": False}
except Exception as e:
return {"error": f"Unexpected error: {str(e)}", "success": False}
# Usage
result = safe_vcon_operation(Vcon.load, "conversation.json")
if not result.get("success", True):
print(f"Error: {result['error']}")
4. Validation Patterns
def validate_and_fix_vcon(vcon):
"""Validate vCon and attempt to fix common issues."""
is_valid, errors = vcon.is_valid()
if is_valid:
return {"valid": True, "errors": []}
fixes_applied = []
# Fix common issues
for error in errors:
if "missing uuid" in error.lower():
# UUID is auto-generated, this shouldn't happen
pass
elif "invalid dialog type" in error.lower():
# Try to fix invalid dialog types
for dialog in vcon.dialog:
if dialog.get("type") not in ["text", "recording", "transfer", "incomplete", "audio", "video"]:
dialog["type"] = "text" # Default to text
fixes_applied.append(f"Fixed invalid dialog type: {dialog.get('type')}")
# Re-validate after fixes
is_valid, remaining_errors = vcon.is_valid()
return {
"valid": is_valid,
"errors": remaining_errors,
"fixes_applied": fixes_applied
}
5. Integration Patterns
REST API Integration
def vcon_to_api_payload(vcon):
"""Convert vCon to API payload format."""
return {
"vcon": vcon.to_dict(),
"metadata": {
"version": vcon.vcon,
"created_at": vcon.created_at,
"party_count": len(vcon.parties),
"dialog_count": len(vcon.dialog)
}
}
def api_payload_to_vcon(payload):
"""Convert API payload to vCon."""
return Vcon(payload["vcon"])
Database Integration
def vcon_to_database_record(vcon):
"""Convert vCon to database record format."""
return {
"id": vcon.uuid,
"version": vcon.vcon,
"created_at": vcon.created_at,
"updated_at": vcon.updated_at,
"data": vcon.to_json(),
"party_count": len(vcon.parties),
"dialog_count": len(vcon.dialog),
"has_attachments": len(vcon.attachments) > 0,
"has_analysis": len(vcon.analysis) > 0
}
6. Performance Considerations
def optimize_vcon_for_storage(vcon):
"""Optimize vCon for storage by converting large content to external references."""
for i, dialog in enumerate(vcon.dialog):
if dialog.get("body") and len(dialog["body"]) > 1000000: # 1MB threshold
# In real implementation, upload to storage and get URL
external_url = f"https://storage.example.com/dialog_{i}_content"
dialog["url"] = external_url
dialog["content_hash"] = dialog.calculate_content_hash()
del dialog["body"]
dialog["encoding"] = None
def optimize_vcon_for_processing(vcon):
"""Optimize vCon for processing by loading external content."""
for dialog in vcon.dialog:
if dialog.is_external_data():
try:
dialog.to_inline_data()
except Exception as e:
print(f"Failed to load external content: {e}")
Conclusion
The vCon library provides a comprehensive framework for working with conversation data. When generating code:
Start Simple: Begin with
Vcon.build_new()
and basic Party/Dialog objectsAdd Rich Metadata: Use tags, attachments, and analysis for comprehensive data
Handle Multimedia: Leverage video/image processing capabilities when needed
Ensure Security: Use digital signatures for integrity verification
Validate Always: Check vCon validity before saving or transmitting
Handle Errors Gracefully: Implement proper error handling for robust applications
Consider Performance: Optimize for storage or processing based on use case
Use Extensions: Declare optional features and must-support requirements
Track Events: Use party history for complex multi-party conversations
Integrate Seamlessly: Follow patterns for API and database integration
The vCon 0.3.0 specification provides a robust foundation for modern conversation data management with support for multimedia content, security, and extensibility.
Last updated
Was this helpful?