sales-model 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sales_model-0.1.0/.env +38 -0
- sales_model-0.1.0/.env.example +155 -0
- sales_model-0.1.0/.gitignore +49 -0
- sales_model-0.1.0/AZURE_REDIS_SETUP.md +211 -0
- sales_model-0.1.0/PKG-INFO +107 -0
- sales_model-0.1.0/POSTGRES_SETUP.md +224 -0
- sales_model-0.1.0/PYPI_PUBLISHING.md +97 -0
- sales_model-0.1.0/README.md +69 -0
- sales_model-0.1.0/docker-compose.yml +33 -0
- sales_model-0.1.0/init_db.py +126 -0
- sales_model-0.1.0/publish_testpypi.ps1 +46 -0
- sales_model-0.1.0/pyproject.toml +71 -0
- sales_model-0.1.0/requirements.txt +44 -0
- sales_model-0.1.0/sales_brain.py +730 -0
- sales_model-0.1.0/src/app/__init__.py +0 -0
- sales_model-0.1.0/src/app/auth/__init__.py +0 -0
- sales_model-0.1.0/src/app/auth/api_keys.py +290 -0
- sales_model-0.1.0/src/app/auth/jwt.py +103 -0
- sales_model-0.1.0/src/app/auth/rate_limit.py +41 -0
- sales_model-0.1.0/src/app/auth/rate_limiter.py +354 -0
- sales_model-0.1.0/src/app/auth/security.py +367 -0
- sales_model-0.1.0/src/app/billing/__init__.py +24 -0
- sales_model-0.1.0/src/app/billing/usage.py +488 -0
- sales_model-0.1.0/src/app/dashboard/__init__.py +1 -0
- sales_model-0.1.0/src/app/dashboard/data.py +139 -0
- sales_model-0.1.0/src/app/dashboard/data_backup.py +942 -0
- sales_model-0.1.0/src/app/dashboard/models.py +387 -0
- sales_model-0.1.0/src/app/dashboard/postgres_data.py +1208 -0
- sales_model-0.1.0/src/app/dashboard/routes.py +1006 -0
- sales_model-0.1.0/src/app/main.py +587 -0
- sales_model-0.1.0/src/app/main_v2.py +693 -0
- sales_model-0.1.0/src/app/observability/__init__.py +0 -0
- sales_model-0.1.0/src/app/observability/logging.py +23 -0
- sales_model-0.1.0/src/app/observability/metrics.py +9 -0
- sales_model-0.1.0/src/app/observability/tracing.py +5 -0
- sales_model-0.1.0/src/app/providers/__init__.py +0 -0
- sales_model-0.1.0/src/app/providers/azure_foundry_stt.py +111 -0
- sales_model-0.1.0/src/app/providers/azure_foundry_tts.py +123 -0
- sales_model-0.1.0/src/app/providers/llm_base.py +15 -0
- sales_model-0.1.0/src/app/providers/null_stt.py +28 -0
- sales_model-0.1.0/src/app/providers/null_tts.py +13 -0
- sales_model-0.1.0/src/app/providers/stt_base.py +27 -0
- sales_model-0.1.0/src/app/providers/tts_base.py +8 -0
- sales_model-0.1.0/src/app/sales_brain/__init__.py +0 -0
- sales_model-0.1.0/src/app/sales_brain/brain.py +26 -0
- sales_model-0.1.0/src/app/sales_brain/chunker.py +48 -0
- sales_model-0.1.0/src/app/storage/__init__.py +0 -0
- sales_model-0.1.0/src/app/storage/database.py +761 -0
- sales_model-0.1.0/src/app/storage/postgres.py +17 -0
- sales_model-0.1.0/src/app/storage/redis.py +176 -0
- sales_model-0.1.0/src/app/storage/schema.sql +319 -0
- sales_model-0.1.0/src/app/utils/__init__.py +1 -0
- sales_model-0.1.0/src/app/utils/latency.py +323 -0
- sales_model-0.1.0/src/app/voice/__init__.py +0 -0
- sales_model-0.1.0/src/app/voice/audio.py +8 -0
- sales_model-0.1.0/src/app/voice/session.py +225 -0
- sales_model-0.1.0/src/app/voice/ssml.py +32 -0
- sales_model-0.1.0/src/app/voice/vad.py +6 -0
- sales_model-0.1.0/src/app/voice/voicelive.py +324 -0
- sales_model-0.1.0/src/app/voice/ws.py +144 -0
- sales_model-0.1.0/src/app/webui/app.js +384 -0
- sales_model-0.1.0/src/app/webui/index.html +90 -0
- sales_model-0.1.0/src/app/webui/styles.css +267 -0
- sales_model-0.1.0/src/sales_model/__init__.py +8 -0
- sales_model-0.1.0/src/sales_model/ai.py +54 -0
- sales_model-0.1.0/src/sales_model/cli.py +51 -0
- sales_model-0.1.0/src/sales_model/config.py +37 -0
- sales_model-0.1.0/src/sales_model/context_utils.py +170 -0
- sales_model-0.1.0/src/sales_model/crm.py +20 -0
- sales_model-0.1.0/src/sales_model/inventory.py +144 -0
- sales_model-0.1.0/src/sales_model/playbook.py +37 -0
- sales_model-0.1.0/src/sales_model/prompt_cache.py +14 -0
- sales_model-0.1.0/src/sales_model/prompt_compiler.py +47 -0
- sales_model-0.1.0/src/sales_model/prompt_registry.py +102 -0
- sales_model-0.1.0/src/sales_model/sales_brain.py +731 -0
- sales_model-0.1.0/src/sales_model/schemas.py +57 -0
- sales_model-0.1.0/src/sales_model/status_engine.py +258 -0
- sales_model-0.1.0/src/sales_model/tactics.py +210 -0
- sales_model-0.1.0/test.py +0 -0
- sales_model-0.1.0/test_postgres.py +83 -0
sales_model-0.1.0/.env
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
AZURE_OPENAI_KEY=ATgWBKsrMNKYyorcdYIVAUdJkehd0vuCeBzwbFtLfxowMBb3rcQXJQQJ99BLACHYHv6XJ3w3AAAAACOGBqis
|
|
2
|
+
AZURE_OPENAI_ENDPOINT=https://talos-mjpfnm19-eastus2.cognitiveservices.azure.com/
|
|
3
|
+
AZURE_OPENAI_DEPLOYMENT=gpt-5.2-chat
|
|
4
|
+
AZURE_OPENAI_API_VERSION=2024-12-01-preview
|
|
5
|
+
AZURE_OPENAI_TEMPERATURE=1.0
|
|
6
|
+
AZURE_OPENAI_MAX_TOKENS=500
|
|
7
|
+
SPEECH_KEY=4kU3ZWZ39DP6xmuWLVwUOrz6c3zPDVKi06AReB1Dt0A9Xp3NoFgqJQQJ99CAACHYHv6XJ3w3AAAAACOGiBO4
|
|
8
|
+
SPEECH_REGION=eastus2
|
|
9
|
+
SPEECH_ENDPOINT=https://ai-talosyssolutions-8046.cognitiveservices.azure.com/
|
|
10
|
+
SPEECH_VOICE=en-US-Andrew:DragonHDLatestNeural
|
|
11
|
+
SPEECH_RATE=1.3
|
|
12
|
+
SPEECH_END_SILENCE_MS=600
|
|
13
|
+
SPEECH_INITIAL_SILENCE_MS=4000
|
|
14
|
+
SPEECH_STABLE_PARTIAL=3
|
|
15
|
+
VOICE_ENGINE=voicelive
|
|
16
|
+
AZURE_VOICELIVE_ENDPOINT=https://sales-model-resource.cognitiveservices.azure.com/
|
|
17
|
+
AZURE_VOICELIVE_API_KEY=93474DcNhaYtlGAvYiK1JIoT0JvphtVrOYFQEeu5A9eRilv9fre6JQQJ99CAACYeBjFXJ3w3AAAAACOGwncq
|
|
18
|
+
AZURE_VOICELIVE_REGION=eastus
|
|
19
|
+
VOICELIVE_MODEL=gpt-4o
|
|
20
|
+
VOICELIVE_VOICE=en-US-JennyNeural
|
|
21
|
+
VOICELIVE_INSTRUCTIONS=You are an elite sales agent. Be concise, confident, and outcome-focused. Ask at most one question and keep responses under 2 sentences unless the user asks otherwise.
|
|
22
|
+
VOICE_API_KEY=thisismyvoice
|
|
23
|
+
|
|
24
|
+
# Database Configuration
|
|
25
|
+
DATABASE_URL=postgresql://neondb_owner:npg_wGAKy51MNrkE@ep-withered-brook-ahgiew9l-pooler.c-3.us-east-1.aws.neon.tech/salesdb?sslmode=require&channel_binding=require
|
|
26
|
+
|
|
27
|
+
# Azure Managed Redis Configuration (with Entra ID authentication)
|
|
28
|
+
# Update with your actual Azure Managed Redis hostname
|
|
29
|
+
AZURE_REDIS_HOST=sales-model.eastus.redis.azure.net
|
|
30
|
+
AZURE_REDIS_PORT=10000
|
|
31
|
+
# No password needed - uses Azure Entra ID authentication
|
|
32
|
+
|
|
33
|
+
# Local fallback for development (optional)
|
|
34
|
+
REDIS_URL=redis://localhost:6379/0
|
|
35
|
+
|
|
36
|
+
# Security Keys (generate your own in production)
|
|
37
|
+
JWT_SECRET=myjsonwebtokensecret
|
|
38
|
+
API_KEY_SECRET=verysecretapikeyforauthentication
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# Sales Voice Gateway - Production Configuration
|
|
3
|
+
# =============================================================================
|
|
4
|
+
|
|
5
|
+
# -----------------------------------------------------------------------------
|
|
6
|
+
# Core Settings
|
|
7
|
+
# -----------------------------------------------------------------------------
|
|
8
|
+
# Environment: development, staging, production
|
|
9
|
+
ENVIRONMENT=production
|
|
10
|
+
|
|
11
|
+
# Enable API documentation (disable in production if needed)
|
|
12
|
+
ENABLE_DOCS=true
|
|
13
|
+
|
|
14
|
+
# CORS origins (comma-separated)
|
|
15
|
+
CORS_ORIGINS=https://yourdomain.com,https://app.yourdomain.com
|
|
16
|
+
|
|
17
|
+
# -----------------------------------------------------------------------------
|
|
18
|
+
# Authentication & Security
|
|
19
|
+
# -----------------------------------------------------------------------------
|
|
20
|
+
# JWT secret for token signing (CHANGE IN PRODUCTION!)
|
|
21
|
+
JWT_SECRET=your-super-secret-jwt-key-change-me-in-production
|
|
22
|
+
VOICE_JWT_SECRET=your-voice-jwt-secret-change-me
|
|
23
|
+
|
|
24
|
+
# JWT configuration
|
|
25
|
+
JWT_ISSUER=sales-voice
|
|
26
|
+
JWT_AUDIENCE=sales-voice
|
|
27
|
+
VOICE_ACCESS_TTL_SECONDS=900
|
|
28
|
+
VOICE_SESSION_TTL_SECONDS=120
|
|
29
|
+
|
|
30
|
+
# -----------------------------------------------------------------------------
|
|
31
|
+
# Database Configuration
|
|
32
|
+
# -----------------------------------------------------------------------------
|
|
33
|
+
# PostgreSQL connection string
|
|
34
|
+
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/sales_model
|
|
35
|
+
|
|
36
|
+
# Legacy API key (for backward compatibility)
|
|
37
|
+
VOICE_API_KEY=your-legacy-api-key
|
|
38
|
+
|
|
39
|
+
# Admin API key for managing organization API keys
|
|
40
|
+
ADMIN_API_KEY=your-admin-api-key-for-key-management
|
|
41
|
+
|
|
42
|
+
# Master API key (optional, for system access)
|
|
43
|
+
MASTER_API_KEY=sv_your-master-api-key
|
|
44
|
+
MASTER_ORG_ID=system
|
|
45
|
+
|
|
46
|
+
# API key hashing salt (CHANGE IN PRODUCTION!)
|
|
47
|
+
API_KEY_SALT=your-unique-salt-change-me-in-production
|
|
48
|
+
|
|
49
|
+
# IP allowlisting (optional, comma-separated)
|
|
50
|
+
# ALLOWED_IPS=10.0.0.1,10.0.0.2
|
|
51
|
+
|
|
52
|
+
# -----------------------------------------------------------------------------
|
|
53
|
+
# Azure VoiceLive Configuration
|
|
54
|
+
# -----------------------------------------------------------------------------
|
|
55
|
+
VOICE_ENGINE=voicelive
|
|
56
|
+
|
|
57
|
+
AZURE_VOICELIVE_ENDPOINT=https://your-resource.cognitiveservices.azure.com
|
|
58
|
+
AZURE_VOICELIVE_API_KEY=your-azure-voicelive-key
|
|
59
|
+
AZURE_VOICELIVE_REGION=eastus
|
|
60
|
+
AZURE_VOICELIVE_API_VERSION=2025-05-01-preview
|
|
61
|
+
|
|
62
|
+
VOICELIVE_MODEL=gpt-4o-realtime-preview
|
|
63
|
+
VOICELIVE_VOICE=en-US-JennyNeural
|
|
64
|
+
# VOICELIVE_RATE=+10%
|
|
65
|
+
|
|
66
|
+
# Welcome message
|
|
67
|
+
VOICELIVE_WELCOME_MESSAGE=Hello! I'm your AI sales assistant. How can I help you today?
|
|
68
|
+
|
|
69
|
+
# Voice instructions
|
|
70
|
+
VOICELIVE_INSTRUCTIONS=You are an elite sales professional with a warm, trustworthy voice. Be concise, confident, and customer-focused.
|
|
71
|
+
|
|
72
|
+
# Audio resampling (if voice sounds deep/slow)
|
|
73
|
+
VOICELIVE_TTS_SOURCE_SAMPLE_RATE=24000
|
|
74
|
+
VOICELIVE_CLIENT_SAMPLE_RATE=16000
|
|
75
|
+
# VOICELIVE_DISABLE_RESAMPLE=false
|
|
76
|
+
|
|
77
|
+
# -----------------------------------------------------------------------------
|
|
78
|
+
# Azure Speech Services (TTS/STT)
|
|
79
|
+
# -----------------------------------------------------------------------------
|
|
80
|
+
SPEECH_KEY=your-azure-speech-key
|
|
81
|
+
SPEECH_ENDPOINT=https://your-resource.cognitiveservices.azure.com
|
|
82
|
+
SPEECH_REGION=eastus
|
|
83
|
+
SPEECH_VOICE=en-US-JennyNeural
|
|
84
|
+
|
|
85
|
+
# -----------------------------------------------------------------------------
|
|
86
|
+
# Azure OpenAI
|
|
87
|
+
# -----------------------------------------------------------------------------
|
|
88
|
+
AZURE_OPENAI_ENDPOINT=https://your-openai-resource.openai.azure.com
|
|
89
|
+
AZURE_OPENAI_API_KEY=your-azure-openai-key
|
|
90
|
+
AZURE_OPENAI_DEPLOYMENT=gpt-4o
|
|
91
|
+
AZURE_OPENAI_API_VERSION=2024-08-01-preview
|
|
92
|
+
|
|
93
|
+
# -----------------------------------------------------------------------------
|
|
94
|
+
# Redis Configuration
|
|
95
|
+
# -----------------------------------------------------------------------------
|
|
96
|
+
REDIS_URL=redis://localhost:6379/0
|
|
97
|
+
|
|
98
|
+
# For production with authentication:
|
|
99
|
+
# REDIS_URL=redis://:password@redis-host:6379/0
|
|
100
|
+
|
|
101
|
+
# -----------------------------------------------------------------------------
|
|
102
|
+
# WebSocket Configuration
|
|
103
|
+
# -----------------------------------------------------------------------------
|
|
104
|
+
# Override WebSocket URL if behind a load balancer
|
|
105
|
+
# VOICE_WS_URL=wss://api.yourdomain.com/voice
|
|
106
|
+
|
|
107
|
+
# -----------------------------------------------------------------------------
|
|
108
|
+
# Rate Limiting & Quotas
|
|
109
|
+
# -----------------------------------------------------------------------------
|
|
110
|
+
# Plan limits are configured in code (app/auth/api_keys.py)
|
|
111
|
+
# Override defaults here if needed:
|
|
112
|
+
# FREE_REQUESTS_PER_MINUTE=10
|
|
113
|
+
# PRO_REQUESTS_PER_MINUTE=100
|
|
114
|
+
|
|
115
|
+
# -----------------------------------------------------------------------------
|
|
116
|
+
# Billing & Usage Tracking
|
|
117
|
+
# -----------------------------------------------------------------------------
|
|
118
|
+
# Webhook URL for billing events
|
|
119
|
+
# BILLING_WEBHOOK_URL=https://billing.yourdomain.com/webhooks/usage
|
|
120
|
+
# BILLING_WEBHOOK_SECRET=your-webhook-signing-secret
|
|
121
|
+
|
|
122
|
+
# Additional webhook endpoints for redundancy
|
|
123
|
+
# BILLING_WEBHOOK_URL_1=https://backup-billing.yourdomain.com/webhooks/usage
|
|
124
|
+
|
|
125
|
+
# Pricing (USD)
|
|
126
|
+
PRICE_VOICE_PER_MINUTE=0.02
|
|
127
|
+
PRICE_API_PER_REQUEST=0.0001
|
|
128
|
+
FREE_API_REQUESTS=10000
|
|
129
|
+
|
|
130
|
+
# -----------------------------------------------------------------------------
|
|
131
|
+
# Performance & Latency
|
|
132
|
+
# -----------------------------------------------------------------------------
|
|
133
|
+
WORKER_CONNECTIONS=1000
|
|
134
|
+
KEEPALIVE_TIMEOUT=65
|
|
135
|
+
GRACEFUL_TIMEOUT=30
|
|
136
|
+
MAX_REQUESTS=10000
|
|
137
|
+
MAX_REQUESTS_JITTER=1000
|
|
138
|
+
BUFFER_SIZE=65536
|
|
139
|
+
BACKLOG=2048
|
|
140
|
+
|
|
141
|
+
# -----------------------------------------------------------------------------
|
|
142
|
+
# Logging & Observability
|
|
143
|
+
# -----------------------------------------------------------------------------
|
|
144
|
+
LOG_LEVEL=INFO
|
|
145
|
+
LOG_FORMAT=json
|
|
146
|
+
|
|
147
|
+
# Structured logging fields
|
|
148
|
+
SERVICE_NAME=sales-voice-gateway
|
|
149
|
+
SERVICE_VERSION=2.0.0
|
|
150
|
+
|
|
151
|
+
# -----------------------------------------------------------------------------
|
|
152
|
+
# Development Only
|
|
153
|
+
# -----------------------------------------------------------------------------
|
|
154
|
+
# DEBUG=true
|
|
155
|
+
# RELOAD=true
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyd
|
|
5
|
+
*.so
|
|
6
|
+
*.egg-info/
|
|
7
|
+
.eggs/
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
.vscode/
|
|
12
|
+
.idea/
|
|
13
|
+
*.iml
|
|
14
|
+
|
|
15
|
+
# Virtual environments
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
ENV/
|
|
19
|
+
.env/
|
|
20
|
+
|
|
21
|
+
# Packaging/build outputs
|
|
22
|
+
build/
|
|
23
|
+
dist/
|
|
24
|
+
*.whl
|
|
25
|
+
pip-wheel-metadata/
|
|
26
|
+
|
|
27
|
+
# Test/coverage
|
|
28
|
+
.pytest_cache/
|
|
29
|
+
.coverage
|
|
30
|
+
coverage.xml
|
|
31
|
+
htmlcov/
|
|
32
|
+
|
|
33
|
+
# Type check / lint
|
|
34
|
+
.mypy_cache/
|
|
35
|
+
.ruff_cache/
|
|
36
|
+
.pyright/
|
|
37
|
+
|
|
38
|
+
# Logs
|
|
39
|
+
*.log
|
|
40
|
+
|
|
41
|
+
# OS/editor
|
|
42
|
+
.DS_Store
|
|
43
|
+
Thumbs.db
|
|
44
|
+
.vscode/
|
|
45
|
+
|
|
46
|
+
# Project-specific
|
|
47
|
+
model/dist/
|
|
48
|
+
model/build/
|
|
49
|
+
model/*.egg-info/
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# Azure Managed Redis Setup Guide (Entra ID Authentication)
|
|
2
|
+
|
|
3
|
+
Your application is now configured to use Azure Managed Redis with Microsoft Entra ID authentication (the modern, secure approach).
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
1. **Azure subscription** - create one for free at https://azure.com
|
|
8
|
+
2. **Python 3.7+** language environment
|
|
9
|
+
3. **Azure CLI** installed and authenticated (`az login`)
|
|
10
|
+
|
|
11
|
+
## Dependencies
|
|
12
|
+
|
|
13
|
+
The following packages are automatically included in your requirements.txt:
|
|
14
|
+
- `redis` - The Redis Python client
|
|
15
|
+
- `redis-entraid` - Redis Microsoft Entra ID authentication extension
|
|
16
|
+
- `azure-identity` - Azure authentication library
|
|
17
|
+
|
|
18
|
+
## Azure Managed Redis Setup
|
|
19
|
+
|
|
20
|
+
### 1. Create Azure Managed Redis Cache
|
|
21
|
+
|
|
22
|
+
Using Azure Portal:
|
|
23
|
+
1. Go to Azure Portal → Create a resource → Databases → Azure Managed Redis
|
|
24
|
+
2. Configure:
|
|
25
|
+
- **Resource Group**: Create new or use existing
|
|
26
|
+
- **Cache Name**: Choose a unique name (e.g., `my-app-redis`)
|
|
27
|
+
- **Location**: Choose your preferred region
|
|
28
|
+
- **Pricing tier**: Start with Basic for development
|
|
29
|
+
- **Public endpoint**: Enable for this setup
|
|
30
|
+
- **Microsoft Entra ID**: Enabled by default ✓
|
|
31
|
+
|
|
32
|
+
Using Azure CLI:
|
|
33
|
+
```bash
|
|
34
|
+
# Create resource group (if needed)
|
|
35
|
+
az group create --name my-redis-rg --location eastus
|
|
36
|
+
|
|
37
|
+
# Create Azure Managed Redis cache
|
|
38
|
+
az redisenterprise create \
|
|
39
|
+
--resource-group my-redis-rg \
|
|
40
|
+
--name my-app-redis \
|
|
41
|
+
--location eastus \
|
|
42
|
+
--sku Basic_B0 \
|
|
43
|
+
--tags environment=development
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 2. Add Yourself as Redis User
|
|
47
|
+
|
|
48
|
+
**Important**: You must add yourself as a Redis user to access the cache.
|
|
49
|
+
|
|
50
|
+
Using Azure Portal:
|
|
51
|
+
1. Go to your Redis cache → Data Access Configuration
|
|
52
|
+
2. Click "Add" → "Add Redis User"
|
|
53
|
+
3. Select your user account
|
|
54
|
+
4. Grant appropriate permissions (Redis Contributor)
|
|
55
|
+
|
|
56
|
+
Using Azure CLI:
|
|
57
|
+
```bash
|
|
58
|
+
# Get your user ID
|
|
59
|
+
USER_ID=$(az ad signed-in-user show --query id -o tsv)
|
|
60
|
+
|
|
61
|
+
# Add yourself as Redis user
|
|
62
|
+
az redisenterprise database access-policy-assignment create \
|
|
63
|
+
--resource-group my-redis-rg \
|
|
64
|
+
--cluster-name my-app-redis \
|
|
65
|
+
--database-name default \
|
|
66
|
+
--access-policy-assignment-name my-user \
|
|
67
|
+
--object-id $USER_ID \
|
|
68
|
+
--access-policy-name "Data Contributor"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 3. Get Connection Information
|
|
72
|
+
|
|
73
|
+
From Azure Portal:
|
|
74
|
+
1. Go to your Redis cache → Overview
|
|
75
|
+
2. Copy the **Host name** (e.g., `my-app-redis.eastus.redisenterprise.cache.azure.net`)
|
|
76
|
+
3. Note the **Port**: 10000 (default for Managed Redis)
|
|
77
|
+
|
|
78
|
+
### 4. Update Your .env File
|
|
79
|
+
|
|
80
|
+
```env
|
|
81
|
+
# Update with your actual cache hostname
|
|
82
|
+
AZURE_REDIS_HOST=my-app-redis.eastus.redisenterprise.cache.azure.net
|
|
83
|
+
AZURE_REDIS_PORT=10000
|
|
84
|
+
|
|
85
|
+
# Local fallback (optional)
|
|
86
|
+
REDIS_URL=redis://localhost:6379/0
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 5. Authenticate with Azure
|
|
90
|
+
|
|
91
|
+
Before running your application, authenticate with Azure:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Login to Azure (opens browser)
|
|
95
|
+
az login
|
|
96
|
+
|
|
97
|
+
# Or for non-interactive environments
|
|
98
|
+
az login --service-principal --username <app-id> --password <password> --tenant <tenant>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## How It Works
|
|
102
|
+
|
|
103
|
+
### Authentication Flow
|
|
104
|
+
1. Application uses `DefaultAzureCredential` to authenticate
|
|
105
|
+
2. Tries multiple credential sources in order:
|
|
106
|
+
- Environment variables (service principal)
|
|
107
|
+
- Managed identity (if running on Azure)
|
|
108
|
+
- Azure CLI credentials (`az login`)
|
|
109
|
+
- Interactive browser login
|
|
110
|
+
|
|
111
|
+
### Code Structure
|
|
112
|
+
```python
|
|
113
|
+
# Your Redis client automatically handles:
|
|
114
|
+
credential_provider = create_from_default_azure_credential(
|
|
115
|
+
("https://redis.azure.com/.default",),
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
client = redis.Redis(
|
|
119
|
+
host=redis_host,
|
|
120
|
+
port=10000, # Managed Redis port
|
|
121
|
+
ssl=True,
|
|
122
|
+
credential_provider=credential_provider
|
|
123
|
+
)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Testing the Setup
|
|
127
|
+
|
|
128
|
+
Install dependencies and test:
|
|
129
|
+
```bash
|
|
130
|
+
# Install new dependencies
|
|
131
|
+
pip install -r requirements.txt
|
|
132
|
+
|
|
133
|
+
# Test database and Redis connections
|
|
134
|
+
python test_postgres.py
|
|
135
|
+
|
|
136
|
+
# Start the application
|
|
137
|
+
python -m src.app.main_v2
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Port Configuration
|
|
141
|
+
|
|
142
|
+
- **Azure Managed Redis**: Port **10000** (SSL enabled by default)
|
|
143
|
+
- **Azure Cache for Redis**: Port 6380 (if you use the older service)
|
|
144
|
+
- **Local Redis**: Port 6379 (fallback for development)
|
|
145
|
+
|
|
146
|
+
## Benefits of Entra ID Authentication
|
|
147
|
+
|
|
148
|
+
✅ **No passwords or keys to manage**
|
|
149
|
+
✅ **Azure AD integration with role-based access**
|
|
150
|
+
✅ **Automatic credential rotation**
|
|
151
|
+
✅ **Centralized access management**
|
|
152
|
+
✅ **Audit logging through Azure AD**
|
|
153
|
+
✅ **Works with managed identities**
|
|
154
|
+
|
|
155
|
+
## Production Deployment
|
|
156
|
+
|
|
157
|
+
### Using Managed Identity (Recommended)
|
|
158
|
+
```bash
|
|
159
|
+
# Enable managed identity on your Azure App Service/Container
|
|
160
|
+
az webapp identity assign --resource-group <rg> --name <app-name>
|
|
161
|
+
|
|
162
|
+
# Grant Redis access to the managed identity
|
|
163
|
+
PRINCIPAL_ID=$(az webapp identity show --resource-group <rg> --name <app-name> --query principalId -o tsv)
|
|
164
|
+
|
|
165
|
+
az redisenterprise database access-policy-assignment create \
|
|
166
|
+
--resource-group my-redis-rg \
|
|
167
|
+
--cluster-name my-app-redis \
|
|
168
|
+
--database-name default \
|
|
169
|
+
--access-policy-assignment-name app-identity \
|
|
170
|
+
--object-id $PRINCIPAL_ID \
|
|
171
|
+
--access-policy-name "Data Contributor"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Using Service Principal
|
|
175
|
+
Set these environment variables in production:
|
|
176
|
+
```env
|
|
177
|
+
AZURE_CLIENT_ID=your-app-registration-id
|
|
178
|
+
AZURE_CLIENT_SECRET=your-client-secret
|
|
179
|
+
AZURE_TENANT_ID=your-tenant-id
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Troubleshooting
|
|
183
|
+
|
|
184
|
+
### Authentication Issues
|
|
185
|
+
```bash
|
|
186
|
+
# Check if you're logged in to Azure
|
|
187
|
+
az account show
|
|
188
|
+
|
|
189
|
+
# Re-login if needed
|
|
190
|
+
az login
|
|
191
|
+
|
|
192
|
+
# Check Redis permissions
|
|
193
|
+
az redisenterprise database access-policy-assignment list \
|
|
194
|
+
--resource-group my-redis-rg \
|
|
195
|
+
--cluster-name my-app-redis \
|
|
196
|
+
--database-name default
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Connection Issues
|
|
200
|
+
- Ensure your cache allows public access (for development)
|
|
201
|
+
- Check firewall rules if connection fails
|
|
202
|
+
- Verify the hostname is correct (no https:// prefix needed)
|
|
203
|
+
- Port 10000 is the default for Managed Redis
|
|
204
|
+
|
|
205
|
+
### Fallback Behavior
|
|
206
|
+
The application gracefully falls back:
|
|
207
|
+
1. **Azure Managed Redis** (preferred)
|
|
208
|
+
2. **Local Redis** (development)
|
|
209
|
+
3. **In-memory Redis** (ultimate fallback)
|
|
210
|
+
|
|
211
|
+
This ensures your app works in any environment!
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sales-model
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AI-powered sales assistant with intelligent conversation management, lead scoring, and voice capabilities
|
|
5
|
+
Project-URL: Homepage, https://salesai.com
|
|
6
|
+
Project-URL: Documentation, https://salesai.com/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/salesai/sales-model
|
|
8
|
+
Project-URL: Changelog, https://github.com/salesai/sales-model/releases
|
|
9
|
+
Author-email: SalesAI Team <support@salesai.com>
|
|
10
|
+
License: Proprietary
|
|
11
|
+
Keywords: ai,azure-openai,chatbot,conversation,lead-scoring,llm,sales,voice
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Framework :: FastAPI
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Communications :: Chat
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: aiohttp>=3.13.3
|
|
23
|
+
Requires-Dist: azure-ai-voicelive>=1.0.0b1
|
|
24
|
+
Requires-Dist: azure-cognitiveservices-speech>=1.47.0
|
|
25
|
+
Requires-Dist: fastapi>=0.115.6
|
|
26
|
+
Requires-Dist: httpx>=0.28.1
|
|
27
|
+
Requires-Dist: openai>=2.16.0
|
|
28
|
+
Requires-Dist: pydantic>=2.12.5
|
|
29
|
+
Requires-Dist: pyjwt>=2.9.0
|
|
30
|
+
Requires-Dist: python-dotenv>=1.0.1
|
|
31
|
+
Requires-Dist: redis>=5.0.8
|
|
32
|
+
Requires-Dist: requests>=2.32.5
|
|
33
|
+
Requires-Dist: structlog>=24.4.0
|
|
34
|
+
Requires-Dist: tqdm>=4.67.1
|
|
35
|
+
Requires-Dist: uvicorn>=0.30.1
|
|
36
|
+
Requires-Dist: websockets>=12.0
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# sales-model
|
|
40
|
+
|
|
41
|
+
This folder (`model/`) is a standalone Python package you can build and publish to PyPI.
|
|
42
|
+
|
|
43
|
+
It includes:
|
|
44
|
+
- `sales_model/`: the core sales brain + supporting utilities
|
|
45
|
+
- `app/`: a FastAPI-based voice/API gateway
|
|
46
|
+
|
|
47
|
+
## Local install (editable)
|
|
48
|
+
|
|
49
|
+
From the repo root:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
cd model
|
|
53
|
+
python -m pip install -U pip
|
|
54
|
+
python -m pip install -e .
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Quick sanity check:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
python -c "from sales_model import SalesBrain; print(SalesBrain)"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Build
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
cd model
|
|
67
|
+
python -m pip install -U build
|
|
68
|
+
python -m build
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Artifacts land in `model/dist/`:
|
|
72
|
+
- `*.whl`
|
|
73
|
+
- `*.tar.gz`
|
|
74
|
+
|
|
75
|
+
## Upload to PyPI
|
|
76
|
+
|
|
77
|
+
For CI/CD via GitHub Actions (Trusted Publishing), see `PYPI_PUBLISHING.md`.
|
|
78
|
+
|
|
79
|
+
Create an account/token on PyPI first, then:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
cd model
|
|
83
|
+
python -m pip install -U twine
|
|
84
|
+
python -m twine upload dist/*
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Using the package
|
|
88
|
+
|
|
89
|
+
Install:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pip install sales-model
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Run the CLI:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
sales-brain
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Run the API (example):
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
uvicorn app.main:app --reload
|
|
105
|
+
# or
|
|
106
|
+
uvicorn app.main_v2:app --reload
|
|
107
|
+
```
|