Merge pull request #4237 from pipecat-ai/mb/docstring-fixes-2026-04-03

Docstring fixes for docs auto-generation
This commit is contained in:
Mark Backman
2026-04-03 11:50:20 -04:00
committed by GitHub
22 changed files with 81 additions and 117 deletions

View File

@@ -1,108 +1,60 @@
# Pipecat Documentation
# Pipecat API Documentation
This directory contains the source files for auto-generating Pipecat's server API reference documentation.
## Setup
1. Install documentation dependencies:
```bash
pip install -r requirements.txt
```
2. Make the build scripts executable:
```bash
chmod +x build-docs.sh rtd-test.py
```
This directory contains the source files for auto-generating Pipecat's API reference documentation.
## Building Documentation
From this directory, you can build the documentation in several ways:
### Local Build
From this directory:
```bash
# Using the build script (automatically opens docs when done)
./build-docs.sh
# Build docs (warnings shown but don't fail the build)
cd docs/api && uv run ./build-docs.sh
# Or directly with sphinx-build
sphinx-build -b html . _build/html -W --keep-going
# Build with strict mode (warnings treated as errors)
cd docs/api && uv run ./build-docs.sh --strict
```
### ReadTheDocs Test Build
The build script will:
To test the documentation build process exactly as it would run on ReadTheDocs:
```bash
./rtd-test.py
```
This script:
- Creates a fresh virtual environment
- Installs all dependencies as specified in requirements files
- Handles conflicting dependencies (like grpcio versions for Riva)
- Builds the documentation in an isolated environment
- Provides detailed logging of the build process
Use this script to verify your documentation will build correctly on ReadTheDocs before pushing changes.
## Viewing Documentation
The built documentation will be available at `_build/html/index.html`. To open:
```bash
# On MacOS
open _build/html/index.html
# On Linux
xdg-open _build/html/index.html
# On Windows
start _build/html/index.html
```
1. Install documentation dependencies via `uv sync --group docs`
2. Clean previous build output
3. Run `sphinx-build` to generate HTML documentation
4. Open the result in your browser (macOS)
## Directory Structure
```
.
├── api/ # Auto-generated API documentation
├── _build/ # Built documentation
├── _static/ # Static files (images, css, etc.)
├── conf.py # Sphinx configuration
├── api/ # Auto-generated API documentation (created during build)
├── _build/ # Built documentation output
├── conf.py # Sphinx configuration (mock imports, extensions, etc.)
├── index.rst # Main documentation entry point
├── requirements-base.txt # Base documentation dependencies
├── requirements-riva.txt # Riva-specific dependencies
├── build-docs.sh # Local build script
└── rtd-test.py # ReadTheDocs test build script
└── rtd-test.sh # ReadTheDocs test build script (uses pip, not uv)
```
## Notes
## How It Works
- Documentation is auto-generated from Python docstrings
- Service modules are automatically detected and included
- The build process matches our ReadTheDocs configuration
- Warnings are treated as errors (-W flag) to maintain consistency
- The --keep-going flag ensures all errors are reported
- Dependencies are split into multiple requirements files to handle version conflicts
- `conf.py` runs `sphinx-apidoc` during Sphinx's `setup()` phase to generate `.rst` files from Python source
- Sphinx autodoc imports each module to extract docstrings
- Modules with unavailable dependencies are listed in `autodoc_mock_imports` in `conf.py`
- Napoleon extension converts Google-style docstrings to reStructuredText
## Troubleshooting
If you encounter missing service modules:
**Module not appearing in docs:**
1. Verify the service is installed with its extras: `pip install pipecat-ai[service-name]`
2. Check the build logs for import errors
3. Ensure the service module is properly initialized in the package
4. Run `./rtd-test.py` to test in an isolated environment matching ReadTheDocs
1. Check the build output for `autodoc: failed to import` warnings
2. If the module has an unresolvable import dependency, add it to `autodoc_mock_imports` in `conf.py`
3. Verify the module is importable: `uv run python -c "import pipecat.module.name"`
For dependency conflicts:
**Duplicate object warnings:**
1. Check the requirements files for version specifications
2. Use `rtd-test.py` to verify dependency resolution
3. Consider adding service-specific requirements files if needed
These come from re-export modules or Sphinx discovering the same class through multiple import paths. Usually cosmetic.
For more information:
**Docstring formatting warnings:**
- [ReadTheDocs Configuration](.readthedocs.yaml)
- [Sphinx Documentation](https://www.sphinx-doc.org/)
Docstrings use reStructuredText, not Markdown. Common issues:
- Use `Example::` with indented code blocks, not `` ```python ``
- Ensure blank lines between directive content and subsequent sections
- Use `Parameters:` (not `Attributes:`) for dataclass field documentation to avoid duplicate entries

View File

@@ -1,5 +1,13 @@
#!/bin/bash
# Usage: ./build-docs.sh [--strict]
# --strict: Treat warnings as errors (default: warnings only)
SPHINX_OPTS=""
if [ "$1" = "--strict" ]; then
SPHINX_OPTS="-W --keep-going"
fi
# Build docs using uv
echo "Installing dependencies with uv..."
uv sync --group docs --all-extras --no-extra gstreamer --no-extra local_smart_turn --no-extra moondream --no-extra mlx-whisper
@@ -14,8 +22,7 @@ fi
rm -rf _build
echo "Building documentation..."
# Build docs matching ReadTheDocs configuration
uv run sphinx-build -b html -d _build/doctrees . _build/html -W --keep-going
uv run sphinx-build -b html -d _build/doctrees . _build/html $SPHINX_OPTS
if [ $? -eq 0 ]; then
echo "Documentation built successfully!"

View File

@@ -97,6 +97,8 @@ autodoc_mock_imports = [
"fastapi.middleware",
"fastapi.responses",
"uvicorn",
# Deepgram dependencies
"deepgram",
]
# HTML output settings

View File

@@ -40,7 +40,7 @@ class TranscriptHandler:
Maintains a list of conversation messages and outputs them either to a log
or to a file as they are received. Each message includes its timestamp and role.
Attributes:
Parameters:
messages: List of all processed transcript messages
output_file: Optional path to file where transcript is saved. If None, outputs to log only.
"""

View File

@@ -27,7 +27,7 @@ from pipecat.services.xai.realtime import events
class GrokRealtimeLLMInvocationParams(TypedDict):
"""Context-based parameters for invoking Grok Realtime API.
Attributes:
Parameters:
system_instruction: System prompt/instructions for the session.
messages: List of conversation items formatted for Grok Realtime.
tools: List of tool definitions (function, web_search, x_search, file_search).

View File

@@ -36,7 +36,7 @@ class FrameOrder(Enum):
When multiple parallel pipelines produce output for the same input frame,
this setting determines the order in which those output frames are pushed.
Attributes:
Parameters:
ARRIVAL: Frames are pushed in the order they arrive from any pipeline.
This is the default and matches the behavior of prior versions.
PIPELINE: Frames are pushed in pipeline definition order — all frames

View File

@@ -95,8 +95,8 @@ class GenesysAudioHookSerializer(FrameSerializer):
- Text WebSocket frames for JSON control messages
- Binary WebSocket frames for audio data
Example usage:
```python
Example usage::
serializer = GenesysAudioHookSerializer(
params=GenesysAudioHookSerializer.InputParams(
channel=AudioHookChannel.EXTERNAL,
@@ -122,9 +122,8 @@ class GenesysAudioHookSerializer(FrameSerializer):
# Set output variables to return to Architect
serializer.set_output_variables({"intent": "billing", "resolved": True})
```
Attributes:
Parameters:
PROTOCOL_VERSION: The AudioHook protocol version (currently "2").
"""
@@ -133,7 +132,7 @@ class GenesysAudioHookSerializer(FrameSerializer):
class InputParams(FrameSerializer.InputParams):
"""Configuration parameters for GenesysAudioHookSerializer.
Attributes:
Parameters:
genesys_sample_rate: Sample rate used by Genesys (default: 8000 Hz).
sample_rate: Optional override for pipeline input sample rate.
channel: Which audio channels to process (external, internal, both).
@@ -246,8 +245,8 @@ class GenesysAudioHookSerializer(FrameSerializer):
Args:
variables: Dictionary of custom variables to send to Genesys.
Example:
```python
Example::
# During the conversation, collect data and set it
serializer.set_output_variables({
"intent": "billing_inquiry",
@@ -255,7 +254,6 @@ class GenesysAudioHookSerializer(FrameSerializer):
"summary": "Customer asked about their bill",
"transfer_to": "billing_queue"
})
```
"""
self._output_variables = variables
logger.debug(f"Output variables set: {variables}")
@@ -413,8 +411,8 @@ class GenesysAudioHookSerializer(FrameSerializer):
Returns:
Dictionary of the closed response message.
Example:
```python
Example::
# Pass custom data back to Genesys
serializer.create_closed_response(
output_variables={
@@ -423,7 +421,6 @@ class GenesysAudioHookSerializer(FrameSerializer):
"summary": "Customer asked about their bill"
}
)
```
"""
parameters: Optional[Dict[str, Any]] = None

View File

@@ -520,8 +520,7 @@ class GoogleTTSSettings(TTSSettings):
speaking_rate: float | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
#: .. deprecated:: 0.0.105
#: Use ``GoogleTTSService.Settings`` instead.
#: *Deprecated since 0.0.105:* Use ``GoogleTTSService.Settings`` instead.
GoogleStreamTTSSettings = GoogleTTSSettings

View File

@@ -83,7 +83,7 @@ class HeyGenClient:
1. WebSocket connection for avatar control and audio streaming
2. LiveKit connection for receiving avatar video and audio
Attributes:
Parameters:
HEY_GEN_SAMPLE_RATE (int): The required sample rate for HeyGen's audio processing (24000 Hz)
"""

View File

@@ -269,7 +269,9 @@ class NvidiaSTTService(STTService):
.. deprecated:: 0.0.104
Model cannot be changed after initialization for NVIDIA Riva streaming STT.
Set model and function id in the constructor instead, e.g.::
Set model and function id in the constructor instead.
Example::
NvidiaSTTService(
api_key=...,

View File

@@ -163,7 +163,9 @@ class NvidiaTTSService(TTSService):
.. deprecated:: 0.0.104
Model cannot be changed after initialization for NVIDIA Riva TTS.
Set model and function id in the constructor instead, e.g.::
Set model and function id in the constructor instead.
Example::
NvidiaTTSService(
api_key=...,

View File

@@ -86,7 +86,7 @@ def language_to_sarvam_language(language: Language) -> str:
class ModelConfig:
"""Immutable configuration for a Sarvam STT model.
Attributes:
Parameters:
supports_prompt: Whether the model accepts prompt parameter.
supports_mode: Whether the model accepts mode parameter.
supports_language: Whether the model accepts language parameter.

View File

@@ -75,7 +75,7 @@ except ModuleNotFoundError as e:
class SarvamTTSModel(str, Enum):
"""Available Sarvam TTS models.
Attributes:
Parameters:
BULBUL_V2: Standard TTS model with pitch/loudness control.
- Supports pitch, loudness, pace (0.3-3.0)
- Default sample rate: 22050 Hz
@@ -145,7 +145,7 @@ class SarvamTTSSpeakerV3(str, Enum):
class TTSModelConfig:
"""Immutable configuration for a Sarvam TTS model.
Attributes:
Parameters:
supports_pitch: Whether the model accepts pitch parameter.
supports_loudness: Whether the model accepts loudness parameter.
supports_temperature: Whether the model accepts temperature parameter.

View File

@@ -67,7 +67,7 @@ from pipecat.utils.time import seconds_to_nanoseconds
class TTSContext:
"""Context information for a TTS request.
Attributes:
Parameters:
append_to_context: Whether this TTS output should be appended to the
conversation context after it is spoken.
push_assistant_aggregation: Whether to push an

View File

@@ -168,7 +168,7 @@ class BaseWhisperSTTService(SegmentedSTTService):
include_prob_metrics: If True, enables probability metrics in API response.
Each service implements this differently (see child classes).
Defaults to False.
push_empty_transcripts: - If true, allow empty `TranscriptionFrame` frames to be
push_empty_transcripts: If true, allow empty `TranscriptionFrame` frames to be
pushed downstream instead of discarding them. This is intended for situations
where VAD fires even though the user did not speak. In these cases, it is
useful to know that nothing was transcribed so that the agent can resume

View File

@@ -37,7 +37,7 @@ class WhatsAppClient:
events from WhatsApp, and maintains ongoing call state. It supports both
incoming call handling and call termination through the WhatsApp Cloud API.
Attributes:
Parameters:
_whatsapp_api: WhatsApp API instance for making API calls
_ongoing_calls_map: Dictionary mapping call IDs to WebRTC connections
_ice_servers: List of ICE servers for WebRTC connections

View File

@@ -15,7 +15,7 @@ class ProcessFrameResult(Enum):
Controls whether the strategy loop in the controller continues to the
next strategy or stops early.
Attributes:
Parameters:
CONTINUE: Continue to the next strategy in the loop.
STOP: Stop evaluating further strategies for this frame.
"""

View File

@@ -24,7 +24,7 @@ class UserTurnStartedParams:
contextual information about how the user turn should be handled by the user
aggregator.
Attributes:
Parameters:
enable_user_speaking_frames: Whether the user aggregator should emit
frames indicating user speaking state (e.g., user started speaking)
during the bot's turn. This is typically enabled by default, but may

View File

@@ -24,7 +24,7 @@ class UserTurnStoppedParams:
contextual information about how the end of user turn should be handled by
the user aggregator.
Attributes:
Parameters:
enable_user_speaking_frames: Whether the user aggregator should emit
frames indicating user speaking state (e.g., user stopped speaking).
This is typically enabled by default, but may be disabled when another

View File

@@ -147,7 +147,7 @@ Remember: Focus on conversational completeness and how long the user might need.
class UserTurnCompletionConfig:
"""Configuration for turn completion behavior.
Attributes:
Parameters:
instructions: Custom instructions for turn completion. If not provided,
uses default USER_TURN_COMPLETION_INSTRUCTIONS.
incomplete_short_timeout: Seconds to wait after short incomplete (○) before prompting.
@@ -191,9 +191,7 @@ class UserTurnCompletionLLMServiceMixin:
When incomplete timeouts expire, the mixin automatically prompts the LLM
with a contextual follow-up message to re-engage the user.
Usage:
The LLM service controls when to use turn completion by calling
_push_turn_text instead of push_frame:
Usage example::
# With turn completion:
if self._filter_incomplete_user_turns:
@@ -201,7 +199,10 @@ class UserTurnCompletionLLMServiceMixin:
else:
await self.push_frame(LLMTextFrame(chunk.text))
The mixin requires that the base class has a `push_frame` method compatible
The LLM service controls when to use turn completion by calling
``_push_turn_text`` instead of ``push_frame``.
The mixin requires that the base class has a ``push_frame`` method compatible
with FrameProcessor's signature.
"""

View File

@@ -57,7 +57,7 @@ class UserTurnStrategies:
start: [VADUserTurnStartStrategy, TranscriptionUserTurnStartStrategy]
stop: [TurnAnalyzerUserTurnStopStrategy(LocalSmartTurnAnalyzerV3)]
Attributes:
Parameters:
start: A list of user turn start strategies used to detect when
the user starts speaking.
stop: A list of user turn stop strategies used to decide when

View File

@@ -168,7 +168,9 @@ class LLMContextSummarizationConfig:
.. deprecated:: 0.0.104
Use :class:`LLMAutoContextSummarizationConfig` with a nested
:class:`LLMContextSummaryConfig` instead::
:class:`LLMContextSummaryConfig` instead.
Example::
LLMAutoContextSummarizationConfig(
max_context_tokens=8000,