139 lines
4.1 KiB
Python
139 lines
4.1 KiB
Python
"""
|
|
Contact Information Extraction Example
|
|
|
|
Extracts structured contact information from unstructured text (emails, messages, etc.)
|
|
using JSON outputs mode with Pydantic schema validation.
|
|
"""
|
|
|
|
from pydantic import BaseModel, Field, EmailStr
|
|
from typing import Optional, List
|
|
from anthropic import Anthropic
|
|
import os
|
|
|
|
# Initialize client
|
|
client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
|
|
|
|
|
|
# Define schema with Pydantic
|
|
class ContactInfo(BaseModel):
|
|
"""Structured contact information extracted from text."""
|
|
|
|
name: str = Field(description="Full name of the contact person")
|
|
email: EmailStr = Field(description="Email address")
|
|
phone: Optional[str] = Field(
|
|
None, description="Phone number in any format"
|
|
)
|
|
company: Optional[str] = Field(
|
|
None, description="Company or organization name"
|
|
)
|
|
plan_interest: Optional[str] = Field(
|
|
None, description="Product plan or tier they're interested in"
|
|
)
|
|
demo_requested: bool = Field(
|
|
False, description="Whether they requested a product demo"
|
|
)
|
|
tags: List[str] = Field(
|
|
default_factory=list,
|
|
description="Relevant tags or categories"
|
|
)
|
|
|
|
|
|
def extract_contact(text: str) -> Optional[ContactInfo]:
|
|
"""
|
|
Extract contact information from unstructured text.
|
|
|
|
Args:
|
|
text: Unstructured text containing contact information
|
|
|
|
Returns:
|
|
ContactInfo object with extracted data, or None if request refused
|
|
"""
|
|
try:
|
|
response = client.beta.messages.parse(
|
|
model="claude-sonnet-4-5",
|
|
max_tokens=1024,
|
|
betas=["structured-outputs-2025-11-13"],
|
|
messages=[{
|
|
"role": "user",
|
|
"content": f"Extract contact information from the following text:\n\n{text}"
|
|
}],
|
|
output_format=ContactInfo,
|
|
)
|
|
|
|
# Handle different stop reasons
|
|
if response.stop_reason == "refusal":
|
|
print(f"⚠️ Request refused for safety reasons")
|
|
return None
|
|
|
|
if response.stop_reason == "max_tokens":
|
|
print(f"⚠️ Response truncated - increase max_tokens")
|
|
return None
|
|
|
|
# Return validated contact info
|
|
return response.parsed_output
|
|
|
|
except Exception as e:
|
|
print(f"❌ Error extracting contact: {e}")
|
|
raise
|
|
|
|
|
|
def main():
|
|
"""Run contact extraction examples."""
|
|
|
|
examples = [
|
|
# Example 1: Complete contact info
|
|
"""
|
|
Hi, I'm John Smith from Acme Corp. You can reach me at john.smith@acme.com
|
|
or call me at (555) 123-4567. I'm interested in your Enterprise plan and
|
|
would love to schedule a demo next week.
|
|
""",
|
|
|
|
# Example 2: Minimal info
|
|
"""
|
|
Contact: jane.doe@example.com
|
|
""",
|
|
|
|
# Example 3: Informal message
|
|
"""
|
|
Hey! Bob here. Email me at bob@startup.io if you want to chat about
|
|
the Pro plan. Thanks!
|
|
""",
|
|
|
|
# Example 4: Multiple contacts (extracts first/primary)
|
|
"""
|
|
From: alice@company.com
|
|
CC: support@company.com
|
|
|
|
Hi, I'm Alice Johnson, VP of Engineering at TechCo.
|
|
We're evaluating your platform for our team of 50 developers.
|
|
""",
|
|
]
|
|
|
|
print("=" * 70)
|
|
print("Contact Extraction Examples")
|
|
print("=" * 70)
|
|
|
|
for i, text in enumerate(examples, 1):
|
|
print(f"\n📧 Example {i}:")
|
|
print(f"Input: {text.strip()[:100]}...")
|
|
|
|
contact = extract_contact(text)
|
|
|
|
if contact:
|
|
print(f"\n✅ Extracted Contact:")
|
|
print(f" Name: {contact.name}")
|
|
print(f" Email: {contact.email}")
|
|
print(f" Phone: {contact.phone or 'N/A'}")
|
|
print(f" Company: {contact.company or 'N/A'}")
|
|
print(f" Plan Interest: {contact.plan_interest or 'N/A'}")
|
|
print(f" Demo Requested: {contact.demo_requested}")
|
|
print(f" Tags: {', '.join(contact.tags) if contact.tags else 'None'}")
|
|
else:
|
|
print(f"\n❌ No contact extracted")
|
|
|
|
print("-" * 70)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|