State Selection Voice Chatbot Service - Complete Developer Documentation¶
Service: Voice Chatbot Setup State Machine
Port: 8008
Purpose: Manage 4-step setup flow for voice chatbots (text + voice selection)
Technology: FastAPI (Python 3.9+)
Code Location:/state-selection-voicechatbot-service/src/main.py(140 lines, 3 endpoints)
Owner: Backend Team
Last Updated: 2025-12-26
Table of Contents¶
- Service Overview
- State Machine Flow
- Complete Endpoints
- Comparison with Text & 3D Services
- Deployment
Service Overview¶
The State Selection Voice Chatbot Service is a middle-ground variant between text and 3D chatbots. It requires voice selection but not avatar/greeting configuration, resulting in a 4-step state machine.
Key Responsibilities¶
✅ State Machine - Track progress through 4 setup steps
✅ Voice Selection - Choose from 10 Azure Neural voices
✅ Validation - Verify chatbot type, purpose, and voice
✅ Database Selection - Track CosmosDB vs Milvus choice
✅ Simple Configuration - No avatar or greeting setup
Statistics¶
- Total Lines: 140
- Endpoints: 3
- State Steps: 4 (start → chatbot_type_selected → sitemap_urls_fetched → chatbot_purpose_selected → END)
- Voice Options: 10 (5 male, 5 female)
State Machine Flow¶
4-Step Setup Process¶
graph TD
START["start<br/>(No chatbot found)"]
STEP1["chatbot_type_selected<br/>(voice-chatbot chosen)"]
STEP2["sitemap_urls_fetched<br/>(Data collection done)"]
STEP3["chatbot_purpose_selected<br/>(Purpose chosen)"]
END["END<br/>(Setup complete)"]
START -->|"POST /v2/select-chatbot<br/>chatbot_type=voice-chatbot"| STEP1
STEP1 -->|"POST /v2/save-datacollection-status<br/>(Crawl URLs)"| STEP2
STEP2 -->|"POST /v2/select-purpose<br/>(Sales-Agent, etc.)"| STEP3
STEP3 -->|"POST /v2/save-voice-chatbot-selection<br/>(Purpose + Voice)"| END
style START fill:#ffebee
style STEP1 fill:#fff3e0
style STEP2 fill:#e3f2fd
style STEP3 fill:#e8f5e9
style END fill:#c8e6c9
Comparison:
| Service | Steps | Key Difference |
|---|---|---|
| Text Chatbot (8007) | 3 | No voice selection |
| Voice Chatbot (8008) | 4 | + Voice selection |
| 3D Chatbot (8006) | 6 | + Avatar + Voice + Greeting |
State Check Logic¶
Endpoint: GET /v2/check-voice-selection-state
Code Location: Lines 97-124
Complete Logic:
@app.get("/v2/check-voice-selection-state")
def check_selection_state_voice(user_id: str, project_id: str):
selection = selection_collection.find_one({"user_id": user_id, "project_id": project_id})
# State 1: No selection or not voice chatbot
if not selection or selection.get("chatbot_type") != "voice-chatbot":
return {"state": "start", "message": "No chatbot collection found."}
# State 2: Type selected, waiting for data collection
elif "chatbot_type" in selection and "sitemap_urls" not in selection:
return {"state": "chatbot_type_selected"}
# State 3: Data collected, waiting for purpose
elif "chatbot_type" in selection and "sitemap_urls" in selection and "chatbot_purpose" not in selection:
return {"state": "sitemap_urls_fetched"}
# State 4: Purpose selected, waiting for voice (NEW!)
elif "chatbot_type" in selection and "sitemap_urls" in selection and "chatbot_purpose" in selection and "selection_voice" not in selection:
return {"state": "chatbot_purpose_selected"}
# State 5: All complete (voice selected)
elif "chatbot_type" in selection and "sitemap_urls" in selection and "chatbot_purpose" in selection and "selection_voice" in selection:
return {"state": "END"}
else:
return {"state": "start"}
State Responses:
| State | Meaning | Next Step |
|---|---|---|
start |
No chatbot or not voice | Select chatbot type |
chatbot_type_selected |
Type=voice chosen | Crawl data |
sitemap_urls_fetched |
Data collected | Select purpose |
chatbot_purpose_selected |
Purpose chosen | Select voice ⭐ |
END |
Complete! | Launch chatbot |
Complete Endpoints¶
1. POST /v2/save-voice-chatbot-selection¶
Purpose: FINAL STEP - Save voice chatbot configuration with voice selection
Code Location: Lines 50-95
Request:
POST /v2/save-voice-chatbot-selection
Content-Type: multipart/form-data
user_id=User-123456
project_id=User-123456_Project_1
chatbot_type=voice-chatbot
chatbot_purpose=Service-Agent
selection_voice=Female_2
Supported Purposes:
Sales-AgentService-AgentCustom-AgentInformational-AgentRemote-Physio
Supported Voices:
- Male:
Male_1(Eric),Male_2(Guy),Male_3(Liam),Male_IND(Prabhat) - Female:
Female_1(Ava),Female_2(Jenny),Female_3(Aria),Female_4(Sara),Female_IND(Neerja),Female_IND2(Neerja Expressive)
Validation:
# Validate chatbot_type
if chatbot_type not in ["text-chatbot", "voice-chatbot", "3D-chatbot"]:
return {"error": "Invalid chatbot type selected"}
# Validate chatbot_purpose
if chatbot_purpose not in ["Sales-Agent", "Service-Agent", "Custom-Agent",
"Informational-Agent", "Remote-Physio"]:
return {"error": "Invalid purpose type selected"}
# Validate selection_voice (NEW!)
if selection_voice not in ["Male_1", "Male_2", "Male_3", "Male_IND",
"Female_1", "Female_2", "Female_3", "Female_4",
"Female_IND", "Female_IND2"]:
return {"error": "Invalid voice type selected"}
Database Selection Check:
db_selection = selection_collection.find_one(
{"user_id": user_id, "project_id": project_id},
{"database_type": 1}
)
database_type = db_selection.get("database_type",
os.getenv("DEFAULT_DATABASE", "cosmosdb")) \
if db_selection else os.getenv("DEFAULT_DATABASE", "cosmosdb")
Insert Document:
selection_data = {
"user_id": user_id,
"project_id": project_id,
"chatbot_type": chatbot_type, # "voice-chatbot"
"chatbot_purpose": chatbot_purpose, # "Service-Agent"
"voice": selection_voice, # "Female_2" ⭐ NEW!
"chatbot_registered_at": datetime.utcnow(),
"database_type": database_type
}
result = chatbot_collection.insert_one(selection_data)
Response:
chatbot_selections Document:
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"user_id": "User-123456",
"project_id": "User-123456_Project_1",
"chatbot_type": "voice-chatbot",
"chatbot_purpose": "Service-Agent",
"voice": "Female_2", // ⭐ Voice added!
"chatbot_registered_at": ISODate("2025-01-15T14:00:00Z"),
"database_type": "milvus"
}
Comparison with Text Chatbot:
| Field | Text Chatbot | Voice Chatbot |
|---|---|---|
| chatbot_type | "text-chatbot" | "voice-chatbot" |
| chatbot_purpose | ✅ Yes | ✅ Yes |
| voice | ❌ No | ✅ "Female_2" |
| chatbot_registered_at | ✅ Yes | ✅ Yes |
| database_type | ✅ Yes | ✅ Yes |
2. GET /v2/check-voice-selection-state¶
Purpose: Check current step in setup flow
Code Location: Lines 97-124
Request:
Response (Step 3 - needs voice):
Response (Complete):
3. GET /v2/get-chatbot-selection¶
Purpose: Retrieve saved chatbot configuration
Code Location: Lines 126-136
Request:
Response:
{
"_id": "507f1f77bcf86cd799439011",
"user_id": "User-123456",
"project_id": "User-123456_Project_1",
"chatbot_type": "voice-chatbot",
"chatbot_purpose": "Service-Agent",
"voice": "Female_2",
"chatbot_registered_at": "2025-01-15T14:00:00.000Z",
"database_type": "milvus"
}
Comparison with Text & 3D Services¶
Service Comparison Matrix¶
| Feature | Text (8007) | Voice (8008) | 3D (8006) |
|---|---|---|---|
| Lines of Code | 138 | 140 | 1009 |
| Endpoints | 3 | 3 | 20+ |
| State Steps | 3 | 4 | 6 |
| Voice Selection | ❌ | ✅ | ✅ |
| Avatar Selection | ❌ | ❌ | ✅ |
| Greeting Generation | ❌ | ❌ | ✅ |
| System Prompt Storage | ❌ | ❌ | ✅ |
| Quota Management | ❌ | ❌ | ✅ |
| Email Notifications | ❌ | ❌ | ✅ |
| Azure Dependencies | ❌ | ❌ | ✅ |
Complexity Order: Text (simplest) → Voice (middle) → 3D (most complex)
State Step Comparison¶
TEXT CHATBOT (3 steps):
1. Select type → 2. Crawl data → 3. Select purpose → END
VOICE CHATBOT (4 steps):
1. Select type → 2. Crawl data → 3. Select purpose → 4. Select voice → END
3D CHATBOT (6 steps):
1. Select type → 2. Crawl data → 3. Select purpose → 4. Select avatar → 5. Select voice → 6. Final save → END
Voice chatbot adds 1 step: Voice selection between purpose and completion
Voice Options¶
All 10 Azure Neural Voices:
| Voice Code | Name | Gender | Accent |
|---|---|---|---|
Male_1 |
Eric | Male | US |
Male_2 |
Guy | Male | US |
Male_3 |
Liam | Male | Canadian |
Male_IND |
Prabhat | Male | Indian |
Female_1 |
Ava | Female | US (Multilingual) |
Female_2 |
Jenny | Female | US |
Female_3 |
Aria | Female | US |
Female_4 |
Sara | Female | US |
Female_IND |
Neerja | Female | Indian |
Female_IND2 |
Neerja Expressive | Female | Indian |
Used By:
- Voice Chatbot Service (8008) - for voice bot responses
- 3D Chatbot Service (8006) - for avatar voice + greeting TTS
Deployment¶
Docker Configuration¶
Dockerfile:
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY src/ .
EXPOSE 8008
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8008"]
Requirements.txt¶
fastapi>=0.95.0
uvicorn[standard]>=0.22.0
pymongo>=4.3.3
python-multipart>=0.0.6
python-dotenv>=1.0.0
httpx>=0.25.0
Same as text chatbot - no additional dependencies
Environment Variables¶
# Database
MONGO_URI=mongodb://...
MONGO_DB_NAME=Machine_agent_demo
# Database default (CosmosDB or Milvus)
DEFAULT_DATABASE=cosmosdb
# DataDog
DD_SERVICE=state-selection-voicechatbot-service
DD_ENV=production
Performance Metrics¶
| Operation | Latency | Notes |
|---|---|---|
| Check state | 10-20ms | Simple query |
| Save voice chatbot | 30-50ms | Single insert |
| Get chatbot selection | 10-20ms | Simple query |
Same performance as text chatbot - no TTS or external API calls during setup
Security Analysis¶
Good Practices¶
✅ No Hardcoded Credentials - Unlike 3D service
✅ Voice Validation - 10 specific allowed voices
✅ No External API Calls - Reduced attack surface
Missing Features¶
⚠️ No Quota Enforcement - Users can create unlimited voice chatbots
⚠️ No Rate Limiting - Should limit chatbot creation rate
⚠️ CORS Allow All - Same issue as other services
Usage Example¶
Complete Voice Chatbot Setup Flow¶
Step 1: Select Type
response = requests.post(
"http://localhost:8004/v2/select-chatbot",
data={
"user_id": "User-123456",
"project_id": "User-123456_Project_1",
"chatbot_type": "voice-chatbot"
}
)
# State: "chatbot_type_selected"
Step 2: Crawl Data
response = requests.post(
"http://localhost:8005/extract-contents",
data={
"user_id": "User-123456",
"project_id": "User-123456_Project_1",
"domain": "https://example.com",
"urls": "https://example.com/page1,https://example.com/page2"
}
)
requests.post(
"http://localhost:8006/v2/save-datacollection-status",
data={
"user_id": "User-123456",
"project_id": "User-123456_Project_1"
}
)
# State: "sitemap_urls_fetched"
Step 3: Select Purpose
response = requests.post(
"http://localhost:8004/v2/select-purpose",
data={
"user_id": "User-123456",
"project_id": "User-123456_Project_1",
"chatbot_purpose": "Service-Agent"
}
)
# State: "chatbot_purpose_selected"
Step 4: Select Voice & Save
response = requests.post(
"http://localhost:8008/v2/save-voice-chatbot-selection",
data={
"user_id": "User-123456",
"project_id": "User-123456_Project_1",
"chatbot_type": "voice-chatbot",
"chatbot_purpose": "Service-Agent",
"selection_voice": "Female_2" # ⭐ Voice selection!
}
)
# State: "END"
Total Time: ~1 minute (vs 30 seconds for text, 3-5 minutes for 3D)
When to Use Voice Chatbot¶
Use Voice Chatbot (8008) when:
- ✅ Want voice interaction without visual avatar
- ✅ Phone/mobile-first experience
- ✅ Accessibility important (voice for visually impaired)
- ✅ Multi-tasking users (hands-free interaction)
- ✅ Between text-only and full 3D experience
Don't Use Voice Chatbot when:
- ❌ Text-only is sufficient → Use Text Chatbot (8007)
- ❌ Want full visual experience → Use 3D Chatbot (8006)
Related Documentation¶
- State Selection Text Chatbot Service - Simpler variant (no voice)
- State Selection 3D Chatbot Service - Full-featured variant
- Selection Chatbot Service - Individual selection endpoints
- Data Crawling Service - Content extraction
Recommendations¶
Improvements¶
- Add Quota Enforcement - Check chatbot limits before creation
- Add Rate Limiting - Prevent spam
- Add System Prompt Storage - Even voice chatbots need prompts
- Add Voice Preview - Let users hear voice samples before selection
Code Quality¶
- Add Type Hints - Improve readability
- Add Unit Tests - Test state machine logic with voice
- Standardized Logging - Use logger module consistently
Last Updated: 2025-12-26
Code Version: state-selection-voicechatbot-service/src/main.py (140 lines)
Total Endpoints: 3
Review Cycle: Quarterly
"The voice of your brand."