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 identity

  • jCard: 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 coordinates

  • validation: Validation status

  • stir: STIR verification for secure telephony

Metadata:

  • uuid: Unique identifier for the party

  • contact_list: Reference to contact list

  • meta: Additional metadata dictionary

  • Custom 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:

  1. Start Simple: Begin with Vcon.build_new() and basic Party/Dialog objects

  2. Add Rich Metadata: Use tags, attachments, and analysis for comprehensive data

  3. Handle Multimedia: Leverage video/image processing capabilities when needed

  4. Ensure Security: Use digital signatures for integrity verification

  5. Validate Always: Check vCon validity before saving or transmitting

  6. Handle Errors Gracefully: Implement proper error handling for robust applications

  7. Consider Performance: Optimize for storage or processing based on use case

  8. Use Extensions: Declare optional features and must-support requirements

  9. Track Events: Use party history for complex multi-party conversations

  10. 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?