* Adds pipecat.runner.run - FastAPI-based development server with automatic bot discovery * Adds new RunnerArguments types for different transports * Adds new runner utils for creating transports and parsing data * Adds new Daily and LiveKit utils for setup
297 lines
8.0 KiB
Python
297 lines
8.0 KiB
Python
import logging
|
|
import sys
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
# Configure logging
|
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
|
|
logger = logging.getLogger("sphinx-build")
|
|
|
|
# Add source directory to path
|
|
docs_dir = Path(__file__).parent
|
|
project_root = docs_dir.parent.parent
|
|
sys.path.insert(0, str(project_root / "src"))
|
|
|
|
# Project information
|
|
project = "pipecat-ai"
|
|
current_year = datetime.now().year
|
|
copyright = f"2024-{current_year}, Daily" if current_year > 2024 else "2024, Daily"
|
|
author = "Daily"
|
|
|
|
# General configuration
|
|
extensions = [
|
|
"sphinx.ext.autodoc",
|
|
"sphinx.ext.napoleon",
|
|
"sphinx.ext.viewcode",
|
|
"sphinx.ext.intersphinx",
|
|
]
|
|
|
|
suppress_warnings = [
|
|
"autodoc.mocked_object",
|
|
]
|
|
|
|
# Napoleon settings
|
|
napoleon_google_docstring = True
|
|
napoleon_include_init_with_doc = True
|
|
|
|
# AutoDoc settings
|
|
autodoc_default_options = {
|
|
"members": True,
|
|
"member-order": "bysource",
|
|
"undoc-members": False,
|
|
"exclude-members": "__weakref__,model_config",
|
|
"show-inheritance": True,
|
|
}
|
|
|
|
# Mock imports for optional dependencies
|
|
autodoc_mock_imports = [
|
|
"riva",
|
|
"livekit",
|
|
"pyht", # Base PlayHT package
|
|
"pyht.async_client", # PlayHT specific imports
|
|
"pyht.client",
|
|
"pyht.protos",
|
|
"pyht.protos.api_pb2",
|
|
"pipecat_ai_playht", # PlayHT wrapper
|
|
"aiortc",
|
|
"aiortc.mediastreams",
|
|
"cv2",
|
|
"av",
|
|
"pyneuphonic",
|
|
"mem0",
|
|
"mlx_whisper",
|
|
"anthropic",
|
|
"assemblyai",
|
|
"boto3",
|
|
"azure",
|
|
"cartesia",
|
|
"deepgram",
|
|
"elevenlabs",
|
|
"fal",
|
|
"gladia",
|
|
"google",
|
|
"krisp",
|
|
"langchain",
|
|
"lmnt",
|
|
"noisereduce",
|
|
"openpipe",
|
|
"simli",
|
|
"soundfile",
|
|
"soniox",
|
|
"pipecat_ai_krisp",
|
|
"pyaudio",
|
|
"_tkinter",
|
|
"tkinter",
|
|
"daily",
|
|
"daily_python",
|
|
# Moondream dependencies
|
|
"torch",
|
|
"transformers",
|
|
"intel_extension_for_pytorch",
|
|
# Ultravox dependencies
|
|
"huggingface_hub",
|
|
"vllm",
|
|
"vllm.engine.arg_utils",
|
|
"transformers.AutoTokenizer",
|
|
# Langchain dependencies
|
|
"langchain_core",
|
|
"langchain_core.messages",
|
|
"langchain_core.runnables",
|
|
"langchain_core.messages.AIMessageChunk",
|
|
"langchain_core.runnables.Runnable",
|
|
# LiveKit dependencies
|
|
"livekit",
|
|
"livekit.rtc",
|
|
"livekit_api",
|
|
"livekit_protocol",
|
|
"tenacity",
|
|
"tenacity.retry",
|
|
"tenacity.stop_after_attempt",
|
|
"tenacity.wait_exponential",
|
|
"rtc",
|
|
"rtc.Room",
|
|
"rtc.RoomOptions",
|
|
"rtc.AudioSource",
|
|
"rtc.LocalAudioTrack",
|
|
"rtc.TrackPublishOptions",
|
|
"rtc.TrackSource",
|
|
"rtc.AudioStream",
|
|
"rtc.AudioFrameEvent",
|
|
"rtc.AudioFrame",
|
|
"rtc.Track",
|
|
"rtc.TrackKind",
|
|
"rtc.RemoteParticipant",
|
|
"rtc.RemoteTrackPublication",
|
|
"rtc.DataPacket",
|
|
# Riva dependencies
|
|
"riva",
|
|
"riva.client",
|
|
"riva.client.Auth",
|
|
"riva.client.ASRService",
|
|
"riva.client.StreamingRecognitionConfig",
|
|
"riva.client.RecognitionConfig",
|
|
"riva.client.AudioEncoding",
|
|
"riva.client.proto.riva_tts_pb2",
|
|
"riva.client.SpeechSynthesisService",
|
|
# Local CoreML Smart Turn dependencies
|
|
"coremltools",
|
|
"coremltools.models",
|
|
"coremltools.models.MLModel",
|
|
"torch",
|
|
"torch.nn",
|
|
"torch.nn.functional",
|
|
"transformers",
|
|
"transformers.AutoFeatureExtractor",
|
|
# Also add specific classes that are imported
|
|
"AutoFeatureExtractor",
|
|
# Sentry dependencies
|
|
"sentry_sdk",
|
|
# AWS Nova Sonic dependencies
|
|
"aws_sdk_bedrock_runtime",
|
|
"aws_sdk_bedrock_runtime.client",
|
|
"aws_sdk_bedrock_runtime.config",
|
|
"aws_sdk_bedrock_runtime.models",
|
|
"smithy_aws_core",
|
|
"smithy_aws_core.credentials_resolvers",
|
|
"smithy_aws_core.credentials_resolvers.static",
|
|
"smithy_aws_core.identity",
|
|
"smithy_core",
|
|
"smithy_core.aio",
|
|
"smithy_core.aio.eventstream",
|
|
# MCP dependencies (you may already have these)
|
|
"mcp",
|
|
"mcp.client",
|
|
"mcp.client.session_group",
|
|
"mcp.client.sse",
|
|
"mcp.client.stdio",
|
|
"mcp.ClientSession",
|
|
"mcp.StdioServerParameters",
|
|
# gstreamer
|
|
"gi",
|
|
"gi.require_version",
|
|
"gi.repository",
|
|
# Protobuf mocks
|
|
"pipecat.frames.protobufs.frames_pb2",
|
|
"pipecat.serializers.protobuf",
|
|
"google.protobuf",
|
|
"google.protobuf.descriptor",
|
|
"google.protobuf.descriptor_pool",
|
|
"google.protobuf.runtime_version",
|
|
"google.protobuf.symbol_database",
|
|
"google.protobuf.internal.builder",
|
|
]
|
|
|
|
# HTML output settings
|
|
html_theme = "sphinx_rtd_theme"
|
|
html_static_path = ["_static"]
|
|
autodoc_typehints = "signature" # Show type hints in the signature only, not in the docstring
|
|
html_show_sphinx = False
|
|
|
|
|
|
def import_core_modules():
|
|
"""Import core pipecat modules for autodoc to discover."""
|
|
core_modules = [
|
|
"pipecat",
|
|
"pipecat.frames",
|
|
"pipecat.pipeline",
|
|
"pipecat.processors",
|
|
"pipecat.services",
|
|
"pipecat.transports",
|
|
"pipecat.audio",
|
|
"pipecat.adapters",
|
|
"pipecat.clocks",
|
|
"pipecat.metrics",
|
|
"pipecat.observers",
|
|
"pipecat.runner",
|
|
"pipecat.serializers",
|
|
"pipecat.sync",
|
|
"pipecat.transcriptions",
|
|
"pipecat.utils",
|
|
]
|
|
|
|
for module_name in core_modules:
|
|
try:
|
|
__import__(module_name)
|
|
logger.info(f"Successfully imported {module_name}")
|
|
except ImportError as e:
|
|
logger.warning(f"Failed to import {module_name}: {e}")
|
|
|
|
|
|
def clean_title(title: str) -> str:
|
|
"""Automatically clean module titles."""
|
|
# Remove everything after space (like 'module', 'processor', etc.)
|
|
title = title.split(" ")[0]
|
|
|
|
# Get the last part of the dot-separated path
|
|
parts = title.split(".")
|
|
title = parts[-1]
|
|
|
|
return title
|
|
|
|
|
|
def setup(app):
|
|
"""Generate API documentation during Sphinx build."""
|
|
from sphinx.ext.apidoc import main
|
|
|
|
docs_dir = Path(__file__).parent
|
|
project_root = docs_dir.parent.parent
|
|
output_dir = str(docs_dir / "api")
|
|
source_dir = str(project_root / "src" / "pipecat")
|
|
|
|
# Clean existing files
|
|
if Path(output_dir).exists():
|
|
import shutil
|
|
|
|
shutil.rmtree(output_dir)
|
|
logger.info(f"Cleaned existing documentation in {output_dir}")
|
|
|
|
logger.info(f"Generating API documentation...")
|
|
logger.info(f"Output directory: {output_dir}")
|
|
logger.info(f"Source directory: {source_dir}")
|
|
|
|
excludes = [
|
|
str(project_root / "src/pipecat/pipeline/to_be_updated"),
|
|
str(project_root / "src/pipecat/examples"),
|
|
str(project_root / "src/pipecat/tests"),
|
|
"**/test_*.py",
|
|
"**/tests/*.py",
|
|
]
|
|
|
|
try:
|
|
main(
|
|
[
|
|
"-f", # Force overwriting
|
|
"-e", # Don't generate empty files
|
|
"-M", # Put module documentation before submodule documentation
|
|
"--no-toc", # Don't create a table of contents file
|
|
"--separate", # Put documentation for each module in its own page
|
|
"--module-first", # Module documentation before submodule documentation
|
|
"--implicit-namespaces", # Added: Handle implicit namespace packages
|
|
"-o",
|
|
output_dir,
|
|
source_dir,
|
|
]
|
|
+ excludes
|
|
)
|
|
|
|
logger.info("API documentation generated successfully!")
|
|
|
|
# Process generated RST files to update titles
|
|
for rst_file in Path(output_dir).glob("**/*.rst"): # Changed to recursive glob
|
|
content = rst_file.read_text()
|
|
lines = content.split("\n")
|
|
|
|
# Find and clean up the title
|
|
if lines and "=" in lines[1]: # Title is typically the first line
|
|
old_title = lines[0]
|
|
new_title = clean_title(old_title)
|
|
content = content.replace(old_title, new_title)
|
|
rst_file.write_text(content)
|
|
logger.info(f"Updated title: {old_title} -> {new_title}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error generating API documentation: {e}", exc_info=True)
|
|
|
|
|
|
import_core_modules()
|