Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 95 additions & 4 deletions sample_solutions/PDFToPodcast/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Backend Configuration
#########################################################################################################
# Backend Service Configuration
#########################################################################################################

CORS_ORIGINS=http://localhost:3000

# Service URLs (for local development)
Expand All @@ -7,14 +10,102 @@ LLM_SERVICE_URL=http://llm-service:8002
TTS_SERVICE_URL=http://tts-service:8003
BACKEND_API_URL=http://localhost:8000

# File Upload Configuration
MAX_FILE_SIZE=10485760 # 10MB in bytes

# Environment
NODE_ENV=development
PYTHON_ENV=development


#########################################################################################################
# PDF Service Configuration
#########################################################################################################

# Service Configuration
PDF_SERVICE_NAME="PDF Processing Service"
PDF_SERVICE_VERSION=1.0.0
PDF_SERVICE_PORT=8001

# File Processing
MAX_FILE_SIZE=10485760
UPLOAD_DIR=uploads

# OCR Settings
# TESSERACT_CMD=/usr/bin/tesseract
OCR_LANGUAGE=eng
OCR_DPI=300

# Text Processing
ENABLE_TEXT_CLEANING=true
ENABLE_OCR_FALLBACK=true


#########################################################################################################
# LLM Service Configuration
#########################################################################################################

# Inference API Configuration
# Note: model names must match one of the deployed models with Enterprise Inference.
# INFERENCE_API_ENDPOINT: URL to your inference service (without /v1 suffix). Uncomment ONE of the below.
# - For GenAI Gateway:
#INFERENCE_API_ENDPOINT=https://api.example.com
# - For APISIX Gateway (default), requires the model name in the URL path:
INFERENCE_API_ENDPOINT=https://api.example.com/DeepSeek-R1-Distill-Qwen-32B

# INFERENCE_API_TOKEN: Authentication token/API key for the inference service
# - For GenAI Gateway: Your GenAI Gateway API key
# - For APISIX Gateway: Your APISIX authentication token
INFERENCE_API_TOKEN=your-pre-generated-token-here

# Model Configuration
# IMPORTANT: Use the full model name i.e. model card
INFERENCE_MODEL_NAME=deepseek-ai/DeepSeek-R1-Distill-Qwen-32B

# Service Configuration
LLM_SERVICE_NAME="LLM Script Generation Service"
LLM_SERVICE_VERSION=1.0.0
LLM_SERVICE_PORT=8002

# Model Settings
DEFAULT_TONE=conversational
DEFAULT_MAX_LENGTH=2000

# Generation Parameters
TEMPERATURE=0.7
MAX_TOKENS=4000
MAX_RETRIES=3

# Local URL Endpoint (only needed for non-public domains)
# If using a local domain like api.example.com mapped to localhost, set to the domain without https://
# Otherwise, set to: not-needed
LOCAL_URL_ENDPOINT=not-needed

# SSL Verification Settings
# Set to false only for dev with self-signed certs
VERIFY_SSL=true


#########################################################################################################
# TTS Service Configuration
#########################################################################################################

# OpenAI API Configuration (Required for TTS)
OPENAI_API_KEY=your-openai-api-key-here

# Service Configuration
TTS_SERVICE_NAME="TTS Audio Generation Service"
TTS_SERVICE_VERSION=1.0.0
TTS_SERVICE_PORT=8003

# TTS Settings
TTS_MODEL=tts-1-hd
DEFAULT_HOST_VOICE=alloy
DEFAULT_GUEST_VOICE=nova

# Audio Settings
OUTPUT_DIR=/tmp/static/audio
AUDIO_FORMAT=mp3
AUDIO_BITRATE=192k
SILENCE_DURATION_MS=500

# Processing
MAX_CONCURRENT_REQUESTS=5
MAX_SCRIPT_LENGTH=100
105 changes: 40 additions & 65 deletions sample_solutions/PDFToPodcast/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,16 @@ This application is built using FastAPI microservices architecture with Docker c
Before you begin, ensure you have the following installed:

- **Docker and Docker Compose**
- **Enterprise inference endpoint access** (token-based authentication)
- **Enterprise Inference endpoint access** (token-based authentication, see below for models and configs)

#### Deploy Required Models

See the table below for supported models, hardware, and gateway configuration.

| Model | Xeon w/APISIX/Keycloak | Xeon w/GenAI Gateway | Gaudi w/APISIX/Keycloak | Gaudi w/GenAI Gateway |
|---|:---:|:---:|:---:|:---:|
| **deepseek-ai/DeepSeek-R1-Distill-Qwen-32B** | ❌ | ❌ | ✅ Validated on Dell XE7740 | ✅ Validated on Dell XE7740 |
| **Qwen/Qwen3-4B-Instruct-2507** | ✅ Validated on Dell XE7740 | ✅ Validated on Dell XE7740 | ❌ | ❌ |

### Verify Docker Installation

Expand All @@ -119,7 +128,7 @@ docker compose version
docker ps
```

### Required API Keys
### Required API Configuration

**For LLM Service (Script Generation):**

Expand All @@ -136,11 +145,6 @@ This application supports multiple inference deployment patterns:
- To generate the APISIX authentication token, use the [generate-token.sh](https://github.com/opea-project/Enterprise-Inference/blob/main/core/scripts/generate-token.sh) script
- The token is generated using Keycloak client credentials

Configuration requirements:
- INFERENCE_API_ENDPOINT: URL to your inference service (example: https://api.example.com)
- INFERENCE_API_TOKEN: Authentication token/API key for your chosen service
- INFERENCE_MODEL_NAME: Model name (default: deepseek-ai/DeepSeek-R1-Distill-Qwen-32B)

**For TTS Service (Audio Generation):**

OpenAI API Key for text-to-speech:
Expand All @@ -149,22 +153,6 @@ OpenAI API Key for text-to-speech:
- Key format starts with `sk-proj-`
- Requires access to TTS APIs (tts-1-hd model)

### Local Development Configuration

**For Local Testing Only**

If you're testing with a local inference endpoint using a custom domain (e.g., `api.example.com` mapped to localhost in your hosts file):

1. Edit `api/llm-service/.env` and set:
```bash
LOCAL_URL_ENDPOINT=inference.example.com
```
(Use the domain name from your INFERENCE_API_ENDPOINT without `https://`)

2. This allows Docker containers to resolve your local domain correctly.

**Note:** For public domains or cloud-hosted endpoints, leave the default value `not-needed`.

---

## Quick Start Deployment
Expand All @@ -178,43 +166,39 @@ cd Enterprise-Inference/sample_solutions/PDFToPodcast

### Set up the Environment

Each service needs its own `.env` file. Copy the example files and edit with your credentials.

**1. PDF Service Configuration:**

```bash
cp api/pdf-service/.env.example api/pdf-service/.env
```

No changes needed. Uses default values.

**2. TTS Service Configuration:**

```bash
cp api/tts-service/.env.example api/tts-service/.env
```

Open `api/tts-service/.env` and replace `your-openai-api-key-here` with your actual OpenAI API key.

Available TTS voices: alloy, echo, fable, onyx, nova, shimmer. Default voices are alloy (host) and nova (guest).

**3. LLM Service Configuration:**

```bash
cp api/llm-service/.env.example api/llm-service/.env
```

Open `api/llm-service/.env` and configure your inference endpoint with the values from the "Required API Keys" section above.

**Note:** If using a local domain (e.g., `api.example.com` mapped to localhost), also edit `LOCAL_URL_ENDPOINT` and replace `not-needed` with your domain name (without `https://`).

**4. Backend Service Configuration:**
This application requires an `.env` file in the root directory for proper configuration. Create it using [.env.example](./.env.example) with the commands below:

```bash
cp .env.example .env
```

**Note:** If using a local domain (e.g., `api.example.com` mapped to localhost), edit `.env` and replace `not-needed` with your domain name (without `https://`).
Then modify it as needed, with special consideration to certain environment variables mentioned below. Read through the .env file for full instructions.

1. **Backend Service Configuration**
- No changes needed. Use default values.

2. **PDF Service Configuration**
- No changes needed. Use default values.

3. **LLM Service Configuration**
- **INFERENCE_API_ENDPOINT**: Your actual inference service URL (replace `https://api.example.com`)
- For APISIX/Keycloak deployments, the model name must be included in the endpoint URL (e.g., `https://api.example.com/DeepSeek-R1-Distill-Qwen-32B`)
- **INFERENCE_API_TOKEN**: Your actual pre-generated authentication token
- **INFERENCE_MODEL_NAME**: Use the exact model name from your inference service
- To check available models: `curl https://api.example.com/v1/models -H "Authorization: Bearer your-token"`
- **LOCAL_URL_ENDPOINT**: Only needed if using local domain mapping (i.e. `api.example.com` mapped to localhost) for Docker containers to resolve correctly.
- Use the domain name from INFERENCE_API_ENDPOINT without `https://`
- For public domains or cloud-hosted endpoints, leave the default value `not-needed`
- **VERIFY_SSL**: Controls SSL certificate verification (default: `true`)
- Set to `false` only for development environments with self-signed certificates
- Keep as `true` for production environments

4. **TTS Service Configuration**
- **OPENAI_API_KEY**: Replace with actual OpenAI API key
- **DEFAULT_HOST_VOICE**, **DEFAULT_GUEST_VOICE**: Voice used for the podcast
- Default voices are alloy (host) and nova (guest)
- Available TTS voices: alloy, echo, fable, onyx, nova, shimmer

**Note**: The docker-compose.yaml file automatically loads environment variables from `.env` for all services.

### Running the Application

Expand Down Expand Up @@ -318,12 +302,3 @@ docker compose down
For detailed troubleshooting guidance and solutions to common issues, refer to:

[TROUBLESHOOTING_and_ADDITIONAL_INFO.md](./TROUBLESHOOTING_and_ADDITIONAL_INFO.md)

## Additional Info

The following models have been validated with PDFToPodcast:

| Model | Hardware |
|-------|----------|
| **deepseek-ai/DeepSeek-R1-Distill-Qwen-32B** | Gaudi |
| **Qwen/Qwen3-4B-Instruct-2507** | Xeon |
40 changes: 0 additions & 40 deletions sample_solutions/PDFToPodcast/api/llm-service/.env.example

This file was deleted.

6 changes: 3 additions & 3 deletions sample_solutions/PDFToPodcast/api/llm-service/app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ class Settings(BaseSettings):
"""LLM Service Configuration"""

# Service info
SERVICE_NAME: str = "LLM Script Generation Service"
SERVICE_VERSION: str = "1.0.0"
SERVICE_PORT: int = 8002
LLM_SERVICE_NAME: str = "LLM Script Generation Service"
LLM_SERVICE_VERSION: str = "1.0.0"
LLM_SERVICE_PORT: int = 8002

# Inference API Configuration
INFERENCE_API_ENDPOINT: Optional[str] = None
Expand Down
16 changes: 8 additions & 8 deletions sample_solutions/PDFToPodcast/api/llm-service/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@

# Create FastAPI app
app = FastAPI(
title="LLM Script Generation Service",
title=settings.LLM_SERVICE_NAME,
description="Generate podcast scripts from text using AI",
version="1.0.0",
version=settings.LLM_SERVICE_VERSION,
docs_url="/docs",
redoc_url="/redoc"
)
Expand All @@ -43,9 +43,9 @@
async def startup_event():
"""Run on application startup"""
logger.info("=" * 60)
logger.info("LLM Script Generation Service starting up...")
logger.info(f"{settings.LLM_SERVICE_NAME} starting up...")
logger.info("=" * 60)
logger.info(f"Service running on port {settings.SERVICE_PORT}")
logger.info(f"Service running on port {settings.LLM_SERVICE_PORT}")

if settings.INFERENCE_API_ENDPOINT and settings.INFERENCE_API_TOKEN:
logger.info("LLM Provider: Inference API")
Expand All @@ -60,14 +60,14 @@ async def startup_event():
@app.on_event("shutdown")
async def shutdown_event():
"""Run on application shutdown"""
logger.info("LLM Script Generation Service shutting down...")
logger.info(f"{settings.LLM_SERVICE_NAME} shutting down...")

@app.get("/")
async def root():
"""Root endpoint"""
return {
"service": "LLM Script Generation Service",
"version": "1.0.0",
"service": settings.LLM_SERVICE_NAME,
"version": settings.LLM_SERVICE_VERSION,
"description": "Convert text content into engaging podcast dialogue",
"config": {
"llm_provider": "Inference API",
Expand All @@ -86,4 +86,4 @@ async def root():

if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=settings.SERVICE_PORT)
uvicorn.run(app, host="0.0.0.0", port=settings.LLM_SERVICE_PORT)
17 changes: 0 additions & 17 deletions sample_solutions/PDFToPodcast/api/pdf-service/.env.example

This file was deleted.

Loading
Loading