Compare commits
418 Commits
aleix/fram
...
hush/claud
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9f5f44287 | ||
|
|
ecf2e69f3f | ||
|
|
1542d922e7 | ||
|
|
15d5d1159e | ||
|
|
884630a6bd | ||
|
|
1cf137c6a8 | ||
|
|
9c6b11cecf | ||
|
|
061a0dc43d | ||
|
|
328bbe069f | ||
|
|
dc32ecc872 | ||
|
|
f94a60f381 | ||
|
|
a4acc12f91 | ||
|
|
e93112e76e | ||
|
|
680bcaac66 | ||
|
|
d2ac9006a2 | ||
|
|
bcb019e8ab | ||
|
|
4ea546785f | ||
|
|
8951442b8e | ||
|
|
7e6e3031e7 | ||
|
|
3b3c7aa8cc | ||
|
|
308829f92b | ||
|
|
82a799e63e | ||
|
|
6b5bcae86f | ||
|
|
836073849c | ||
|
|
b13b65d6e2 | ||
|
|
3d545b718d | ||
|
|
f2fa5d9733 | ||
|
|
76b774072c | ||
|
|
b6341ffaa5 | ||
|
|
29fae67c9e | ||
|
|
718ea1c15e | ||
|
|
8e09d94614 | ||
|
|
de73e28563 | ||
|
|
55250b4f7e | ||
|
|
281145a991 | ||
|
|
7bd32e2fe5 | ||
|
|
8f05d95f50 | ||
|
|
87c12f3098 | ||
|
|
9c0bf89247 | ||
|
|
6e44a2ab49 | ||
|
|
7aa7b86aed | ||
|
|
5ad9faeb4c | ||
|
|
9e8f8b45c6 | ||
|
|
0ee11ad333 | ||
|
|
124a3c35af | ||
|
|
054e504868 | ||
|
|
e85a00cc0e | ||
|
|
cc61cdbba3 | ||
|
|
62f4708d43 | ||
|
|
ba0ddb1832 | ||
|
|
eacd2a4b71 | ||
|
|
7ed110650d | ||
|
|
4a724379fc | ||
|
|
768d3958dd | ||
|
|
5f9ff8bd58 | ||
|
|
59ed422052 | ||
|
|
7e0ca113af | ||
|
|
13c52e0e6d | ||
|
|
a787fd9cd8 | ||
|
|
14495c425a | ||
|
|
461bd0a2e0 | ||
|
|
bd45ce2b4e | ||
|
|
a266644b06 | ||
|
|
03faadd7f9 | ||
|
|
bf43032652 | ||
|
|
fa6f924b31 | ||
|
|
a010a020fd | ||
|
|
655006aff5 | ||
|
|
671dc8cd9b | ||
|
|
9a718ded1e | ||
|
|
024809b39a | ||
|
|
6cf0d53d00 | ||
|
|
778dacc9a8 | ||
|
|
06b3ecd2d6 | ||
|
|
b4d143e39b | ||
|
|
c89083e72e | ||
|
|
1ac811ab32 | ||
|
|
f6359d460e | ||
|
|
f03a7175c7 | ||
|
|
aed44c863a | ||
|
|
cddd6d5b0a | ||
|
|
11cf891ac8 | ||
|
|
c89ae717fe | ||
|
|
562bdd3084 | ||
|
|
cc4c3650e1 | ||
|
|
dfc1f09b77 | ||
|
|
0b1a4792b8 | ||
|
|
14bd3b1b32 | ||
|
|
f733e77496 | ||
|
|
5fc46cc450 | ||
|
|
4a9eb82f92 | ||
|
|
990d8386e4 | ||
|
|
ce7d823770 | ||
|
|
0b93c3f900 | ||
|
|
829c5f4604 | ||
|
|
dc8ea615d9 | ||
|
|
a3d206050d | ||
|
|
f48a567873 | ||
|
|
e69ccd8ea7 | ||
|
|
11924bb980 | ||
|
|
af89154e96 | ||
|
|
1485ea0831 | ||
|
|
e22bc777d8 | ||
|
|
043403fe23 | ||
|
|
1e1160906e | ||
|
|
f7d3e63063 | ||
|
|
6fa797c8e4 | ||
|
|
473d39791b | ||
|
|
2114abb8c6 | ||
|
|
4fb4c26f55 | ||
|
|
2e8e574ea5 | ||
|
|
84c7e97be2 | ||
|
|
a6e7c99d55 | ||
|
|
ac3fa7f91f | ||
|
|
6eadad53b2 | ||
|
|
b11150f31f | ||
|
|
836cf60611 | ||
|
|
1c13ad95a5 | ||
|
|
1e8516e91d | ||
|
|
32c775311d | ||
|
|
28d0bb98de | ||
|
|
a9a9f3aeaa | ||
|
|
c2a0735975 | ||
|
|
41cb53f6c2 | ||
|
|
58552af8fd | ||
|
|
c7ab87b0cc | ||
|
|
11ecc5fdee | ||
|
|
19fb3eed9f | ||
|
|
b292b32374 | ||
|
|
63d1393bb0 | ||
|
|
37914cb062 | ||
|
|
ec40696854 | ||
|
|
2249f3d673 | ||
|
|
d2df324f29 | ||
|
|
67fdb0b659 | ||
|
|
e77bdf66f9 | ||
|
|
1b3b67779c | ||
|
|
6c7e386391 | ||
|
|
ba25b279d6 | ||
|
|
e7c83c19b6 | ||
|
|
7be7fb49a3 | ||
|
|
bcccb4cbb3 | ||
|
|
e9f1d951d3 | ||
|
|
e5632a9339 | ||
|
|
1510fb4fc0 | ||
|
|
64a1ad2649 | ||
|
|
4458ca1d24 | ||
|
|
21aaa48e62 | ||
|
|
e75c241030 | ||
|
|
60216048a8 | ||
|
|
f3c2e29fb4 | ||
|
|
ce99924be4 | ||
|
|
5de80a60d4 | ||
|
|
5753762350 | ||
|
|
885b318b04 | ||
|
|
7a22d58cf4 | ||
|
|
c8e4b462c9 | ||
|
|
30a3f42255 | ||
|
|
26ddb2de2f | ||
|
|
f60eeaa212 | ||
|
|
8cf72b36cb | ||
|
|
38c3bcef96 | ||
|
|
80604ba7b6 | ||
|
|
256c70c631 | ||
|
|
0e3532c529 | ||
|
|
9942fcfeb2 | ||
|
|
003c24ca6e | ||
|
|
ed120d014d | ||
|
|
e76a3d04f0 | ||
|
|
641d17007f | ||
|
|
9293b5f24a | ||
|
|
c1f3cbd1d4 | ||
|
|
78fa2ab65e | ||
|
|
56da2caeed | ||
|
|
a541d65255 | ||
|
|
a3d7e9eafe | ||
|
|
54933bea2a | ||
|
|
fcab9899cc | ||
|
|
be098e85db | ||
|
|
ed0ff46a87 | ||
|
|
7ae0d651d6 | ||
|
|
efd4432cfb | ||
|
|
24082b84f2 | ||
|
|
dcd5840341 | ||
|
|
9e705ce768 | ||
|
|
965466cc09 | ||
|
|
f3993f1775 | ||
|
|
e107902b14 | ||
|
|
e7b5ff49f4 | ||
|
|
e33172c44e | ||
|
|
3d858e8aa6 | ||
|
|
eab059c49a | ||
|
|
4aaff04fb3 | ||
|
|
cb364f3cab | ||
|
|
a9bfb090c3 | ||
|
|
c4ae4025f3 | ||
|
|
15067c678d | ||
|
|
5ae592f38e | ||
|
|
9cdbc56be3 | ||
|
|
86ed485711 | ||
|
|
7e1b4a4e90 | ||
|
|
4531d517da | ||
|
|
6fd5847f84 | ||
|
|
2015eba9b2 | ||
|
|
84f16ee895 | ||
|
|
5b2af03b16 | ||
|
|
b313395dc3 | ||
|
|
0d6bdbee10 | ||
|
|
248dac3a9d | ||
|
|
be49a54856 | ||
|
|
bd9ee0d646 | ||
|
|
442e0e582d | ||
|
|
38194c0cff | ||
|
|
0ebdaba03c | ||
|
|
ee82377d68 | ||
|
|
861588e4a3 | ||
|
|
1ab3bf2ef6 | ||
|
|
bb00d223c9 | ||
|
|
86fbfaddd1 | ||
|
|
5612bf513b | ||
|
|
87d0dc9e24 | ||
|
|
30fbcfbf71 | ||
|
|
5d90f4ea06 | ||
|
|
f6d09e1574 | ||
|
|
b8e48dee7f | ||
|
|
a6ccb9ec69 | ||
|
|
66551ebdf5 | ||
|
|
21534f7d83 | ||
|
|
d591f9e108 | ||
|
|
aa2589d3be | ||
|
|
9d6067fa78 | ||
|
|
027e54425a | ||
|
|
e268c73c41 | ||
|
|
d3c57e2da0 | ||
|
|
02eace5a16 | ||
|
|
15bc1dd999 | ||
|
|
b937956dc8 | ||
|
|
efbc0c8510 | ||
|
|
d0f227189c | ||
|
|
41eef5efc4 | ||
|
|
f00f9d9f1a | ||
|
|
ae59b3ba36 | ||
|
|
6668712f7b | ||
|
|
8812686b17 | ||
|
|
8b0f0b5bb4 | ||
|
|
f5e8a04e3b | ||
|
|
a298ce3b41 | ||
|
|
31daa889e8 | ||
|
|
76a058178e | ||
|
|
3304b18ac2 | ||
|
|
b95a6afe77 | ||
|
|
f6ed7d7582 | ||
|
|
cd3290df1c | ||
|
|
2296caf529 | ||
|
|
90ded6658d | ||
|
|
7e97fb80a5 | ||
|
|
b58471fdb1 | ||
|
|
46b4f9f29b | ||
|
|
ec20d72aba | ||
|
|
5743e2a99b | ||
|
|
2f429a2e76 | ||
|
|
3e982f7a4a | ||
|
|
89484e281d | ||
|
|
14a115f372 | ||
|
|
e96595fe59 | ||
|
|
f58d21862b | ||
|
|
38506f51f7 | ||
|
|
aac24ad2d4 | ||
|
|
1df9575e20 | ||
|
|
64609fe80f | ||
|
|
533a54e111 | ||
|
|
b59c3eb470 | ||
|
|
0366fc35cb | ||
|
|
d86ff4b1ee | ||
|
|
f8040324e1 | ||
|
|
9c81acb159 | ||
|
|
65395b1112 | ||
|
|
d2696be03b | ||
|
|
2da4d420f9 | ||
|
|
a992f95c02 | ||
|
|
edd8e07df6 | ||
|
|
c813d43da0 | ||
|
|
c973445ab7 | ||
|
|
25f6ba76d6 | ||
|
|
8f47c569f9 | ||
|
|
c16801e524 | ||
|
|
dafcd0448f | ||
|
|
24a52375c7 | ||
|
|
5f9e95038e | ||
|
|
5cbb21afb2 | ||
|
|
119fab2996 | ||
|
|
38d354c4ed | ||
|
|
cdb1074e11 | ||
|
|
4b61fd2d7d | ||
|
|
5a0a5c120b | ||
|
|
d92926ae54 | ||
|
|
b34af5da24 | ||
|
|
5da1f86575 | ||
|
|
b0185e3539 | ||
|
|
7232da6ba1 | ||
|
|
9dff75cd44 | ||
|
|
6038860be0 | ||
|
|
4653de9f03 | ||
|
|
fef79651ef | ||
|
|
3d54ca0a7c | ||
|
|
199986815c | ||
|
|
0a3c00f68b | ||
|
|
3e2467eb71 | ||
|
|
c4cc476c3d | ||
|
|
cc6ff1ac54 | ||
|
|
b075502c4c | ||
|
|
35a99f92ab | ||
|
|
4fe0836cf9 | ||
|
|
8b7cc65ae6 | ||
|
|
4d495ba74f | ||
|
|
de5de0b162 | ||
|
|
311da30802 | ||
|
|
16819a5caa | ||
|
|
72a44c2fcd | ||
|
|
7783b20b91 | ||
|
|
962ccbc0d7 | ||
|
|
4d61c5d7b2 | ||
|
|
7ca4597ade | ||
|
|
f1a22728ab | ||
|
|
ca88fc849f | ||
|
|
ccd795445f | ||
|
|
1874269a48 | ||
|
|
8b20373a8e | ||
|
|
15dcb77a0c | ||
|
|
5d2fac9cd7 | ||
|
|
682b253760 | ||
|
|
f440de82e2 | ||
|
|
5e0e6822c7 | ||
|
|
2aadac7a4d | ||
|
|
1098394486 | ||
|
|
b90a34228f | ||
|
|
8bf8ebd34b | ||
|
|
673d88417c | ||
|
|
3a7b489208 | ||
|
|
7ae9eebc34 | ||
|
|
8f83ba5878 | ||
|
|
b8af3fa214 | ||
|
|
5ddec4f596 | ||
|
|
8f4b4f4941 | ||
|
|
953349f262 | ||
|
|
b52ae0e56b | ||
|
|
893b448534 | ||
|
|
973769b8bc | ||
|
|
c8fa9d34e1 | ||
|
|
3069deb92f | ||
|
|
68c9c01747 | ||
|
|
5e8f0baa12 | ||
|
|
8d1286cc00 | ||
|
|
bda4dd339a | ||
|
|
f2e3034d24 | ||
|
|
2626154a64 | ||
|
|
b770b2a419 | ||
|
|
158c34b0f9 | ||
|
|
d507c88d3e | ||
|
|
98f70b775f | ||
|
|
54f4b824e4 | ||
|
|
2aa5307f0a | ||
|
|
6c10d6ef8a | ||
|
|
89b36f2b25 | ||
|
|
79a6adbcf3 | ||
|
|
95f00a3c4b | ||
|
|
3f8373f76f | ||
|
|
23a9d3f4d7 | ||
|
|
333279f45a | ||
|
|
add5f51201 | ||
|
|
d1bedef5b3 | ||
|
|
54cf0116a8 | ||
|
|
6b252fb46e | ||
|
|
3e00a16f0f | ||
|
|
ecfd93544a | ||
|
|
3ec89e49bf | ||
|
|
8762506e9f | ||
|
|
7204bf9914 | ||
|
|
f62c262f23 | ||
|
|
10aa784809 | ||
|
|
904f5dc183 | ||
|
|
c61a5e7173 | ||
|
|
81b28beef5 | ||
|
|
0d34356678 | ||
|
|
5412840a93 | ||
|
|
137bbb3d2c | ||
|
|
5a40054ac2 | ||
|
|
be621fbc5c | ||
|
|
9ab4836601 | ||
|
|
4671102833 | ||
|
|
67401a275b | ||
|
|
c422588071 | ||
|
|
fb12fec899 | ||
|
|
c53c49558f | ||
|
|
1a26a2daa4 | ||
|
|
d8be1282b5 | ||
|
|
91bc5236b5 | ||
|
|
1ceb01665f | ||
|
|
b278957111 | ||
|
|
1c80c739d6 | ||
|
|
700a94222b | ||
|
|
d5d2156689 | ||
|
|
8203ad08a8 | ||
|
|
31907b90f0 | ||
|
|
7b595f10ce | ||
|
|
4f93d331b7 | ||
|
|
32c6dccebe | ||
|
|
cbdc2b7d2d | ||
|
|
66a9dc70c7 | ||
|
|
846ca500d3 | ||
|
|
bd6afd445d | ||
|
|
0663bbc2fb | ||
|
|
8e7a951af8 | ||
|
|
ba1aeb8f7f | ||
|
|
f7c74cfa80 | ||
|
|
2e700c8576 | ||
|
|
f4626a4fc4 | ||
|
|
e0b40a330f |
8
.claude/.gitignore
vendored
Normal file
8
.claude/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Claude Code temporary files
|
||||
*.tmp
|
||||
*.log
|
||||
.claude-cache/
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
200
.claude/QUICKSTART.md
Normal file
200
.claude/QUICKSTART.md
Normal file
@@ -0,0 +1,200 @@
|
||||
# Claude Code Quick Start for Pipecat
|
||||
|
||||
This guide helps you get started using Claude Code with the Pipecat project.
|
||||
|
||||
## Initial Setup
|
||||
|
||||
1. **Install Claude Code** (if not already installed):
|
||||
```bash
|
||||
# Follow instructions at https://claude.ai/claude-code
|
||||
```
|
||||
|
||||
2. **Install project dependencies**:
|
||||
```bash
|
||||
uv sync --group dev --all-extras --no-extra gstreamer --no-extra krisp --no-extra local
|
||||
```
|
||||
|
||||
3. **Install pre-commit hooks**:
|
||||
```bash
|
||||
uv run pre-commit install
|
||||
```
|
||||
|
||||
## Common Commands
|
||||
|
||||
### Testing
|
||||
- "Run all tests"
|
||||
- "Run tests for [specific file]"
|
||||
- "Run tests and show coverage"
|
||||
|
||||
### Code Quality
|
||||
- "Format the code"
|
||||
- "Fix linting issues"
|
||||
- "Run type checking"
|
||||
- "Run pre-commit hooks"
|
||||
|
||||
### Development
|
||||
- "Add a new TTS service for [provider]"
|
||||
- "Create a new processor that [does something]"
|
||||
- "Add a new frame type for [purpose]"
|
||||
- "Document the [ClassName] class" (uses `/docstring` skill)
|
||||
|
||||
### Documentation
|
||||
- "Document this module using Google style"
|
||||
- "Add docstrings to [file/class]"
|
||||
- Use `/docstring ClassName` for comprehensive class documentation
|
||||
|
||||
### Git Operations
|
||||
- "Create a commit for these changes"
|
||||
- "Create a pull request"
|
||||
- Use `/pr-description` skill for detailed PR descriptions
|
||||
- Use `/changelog` skill for changelog entries
|
||||
|
||||
## Custom Skills
|
||||
|
||||
### `/docstring [ClassName]`
|
||||
Automatically documents a Python class and its methods following Google-style conventions.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
/docstring AudioProcessor
|
||||
```
|
||||
|
||||
This will:
|
||||
- Find the class in the codebase
|
||||
- Add module docstring if missing
|
||||
- Add class docstring with purpose and event handlers
|
||||
- Document all public methods
|
||||
- Document constructor parameters
|
||||
- Skip private methods and already-documented code
|
||||
|
||||
### `/changelog`
|
||||
Generates changelog entries using towncrier.
|
||||
|
||||
### `/pr-description`
|
||||
Creates comprehensive pull request descriptions based on your changes.
|
||||
|
||||
## Project-Specific Tips
|
||||
|
||||
### Understanding Pipecat Architecture
|
||||
|
||||
When asking Claude Code to help with development:
|
||||
|
||||
1. **Frame-Based System**: All data flows through frames
|
||||
- Ask: "Explain how frames work in this pipeline"
|
||||
- Reference: `src/pipecat/frames/frames.py`
|
||||
|
||||
2. **Processor Pattern**: Everything is a processor
|
||||
- Ask: "Show me how to create a custom processor"
|
||||
- Reference: `src/pipecat/processors/frame_processor.py`
|
||||
|
||||
3. **Service Integrations**: Many AI service integrations
|
||||
- Ask: "How do I add a new TTS service?"
|
||||
- Reference: `src/pipecat/services/tts/`
|
||||
|
||||
### Working with Examples
|
||||
|
||||
- "Show me examples of [feature]"
|
||||
- "Create a simple example that [does something]"
|
||||
- Examples are in `examples/foundational/` (building blocks) and `examples/` (complete apps)
|
||||
|
||||
### Debugging
|
||||
|
||||
- "Help me debug this pipeline"
|
||||
- "Why isn't my processor receiving frames?"
|
||||
- "Trace the flow of this frame type through the pipeline"
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Be Specific**: Instead of "fix this", say "fix the audio dropouts in the TTS processor"
|
||||
|
||||
2. **Context**: Provide context about what you're building
|
||||
- "I'm building a voice assistant that needs to interrupt TTS"
|
||||
- "I want to add vision capabilities to this chatbot"
|
||||
|
||||
3. **Reference Examples**: Point to existing patterns
|
||||
- "Similar to how DeepgramTTS works"
|
||||
- "Following the pattern in OpenAILLMService"
|
||||
|
||||
4. **Test-Driven**: Ask for tests
|
||||
- "Create tests for this processor"
|
||||
- "Add test coverage for the error handling"
|
||||
|
||||
5. **Documentation**: Keep docs updated
|
||||
- "Update the docstrings for these changes"
|
||||
- "Add a usage example to the class docstring"
|
||||
|
||||
## Example Conversations
|
||||
|
||||
### Adding a New Feature
|
||||
```
|
||||
You: "I need to add a processor that detects when the user says 'hello' and triggers an event"
|
||||
|
||||
Claude Code will:
|
||||
1. Create the processor class
|
||||
2. Implement frame processing logic
|
||||
3. Add event emission
|
||||
4. Create tests
|
||||
5. Add documentation
|
||||
```
|
||||
|
||||
### Debugging an Issue
|
||||
```
|
||||
You: "The audio is cutting out in my pipeline. Here's the code: [paste code]"
|
||||
|
||||
Claude Code will:
|
||||
1. Analyze the pipeline structure
|
||||
2. Check for common issues (buffer sizes, async handling, etc.)
|
||||
3. Suggest fixes
|
||||
4. Explain the root cause
|
||||
```
|
||||
|
||||
### Refactoring
|
||||
```
|
||||
You: "Refactor the XYZ service to use the new WebSocket pattern from ABC service"
|
||||
|
||||
Claude Code will:
|
||||
1. Analyze both services
|
||||
2. Identify the pattern differences
|
||||
3. Apply the refactoring
|
||||
4. Update tests
|
||||
5. Maintain backward compatibility if needed
|
||||
```
|
||||
|
||||
## Useful Prompts
|
||||
|
||||
- "Explain how [feature] works in this codebase"
|
||||
- "Add error handling for [scenario]"
|
||||
- "Create an example that demonstrates [feature]"
|
||||
- "Optimize this processor for [use case]"
|
||||
- "Add logging to help debug [issue]"
|
||||
- "Make this code more maintainable"
|
||||
- "Add type hints to this file"
|
||||
- "Create a comprehensive test suite for [component]"
|
||||
|
||||
## Configuration Reference
|
||||
|
||||
All Claude Code settings are in [.claude/settings.json](.claude/settings.json):
|
||||
- Project commands (test, lint, format, etc.)
|
||||
- Coding standards
|
||||
- File patterns
|
||||
- Important files and directories
|
||||
|
||||
For detailed architecture info, see [.claude/README.md](.claude/README.md).
|
||||
|
||||
## Getting Help
|
||||
|
||||
- **Project docs**: https://docs.pipecat.ai
|
||||
- **Discord**: https://discord.gg/pipecat
|
||||
- **GitHub Issues**: https://github.com/pipecat-ai/pipecat/issues
|
||||
- **Examples**: https://github.com/pipecat-ai/pipecat-examples
|
||||
|
||||
## Tips for Success
|
||||
|
||||
1. Start with small, specific tasks
|
||||
2. Use the custom skills (`/docstring`, `/pr-description`, etc.)
|
||||
3. Reference existing code patterns
|
||||
4. Ask for explanations when confused
|
||||
5. Request tests and documentation
|
||||
6. Run pre-commit hooks before committing
|
||||
|
||||
Happy coding with Claude! 🎙️🤖
|
||||
177
.claude/README.md
Normal file
177
.claude/README.md
Normal file
@@ -0,0 +1,177 @@
|
||||
# Claude Code Setup for Pipecat
|
||||
|
||||
This directory contains configuration and custom skills for working with the Pipecat project using Claude Code.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Pipecat is an open-source Python framework for building real-time voice and multimodal conversational agents. It provides a composable, frame-based architecture for orchestrating audio, video, AI services, and conversation pipelines.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Core Concepts
|
||||
|
||||
1. **Frames** - The fundamental data units in Pipecat (audio, text, images, system messages, etc.)
|
||||
- Located in: `src/pipecat/frames/frames.py`
|
||||
- Different frame types for different data: `AudioRawFrame`, `TextFrame`, `ImageRawFrame`, etc.
|
||||
|
||||
2. **Processors** - Processing units that receive, transform, and emit frames
|
||||
- Base class: `src/pipecat/processors/frame_processor.py`
|
||||
- Can be chained to form pipelines
|
||||
- Examples: STT services, LLMs, TTS services, aggregators, etc.
|
||||
|
||||
3. **Pipelines** - Chains of processors that define data flow
|
||||
- Created using the `Pipeline` class
|
||||
- Processors linked using `link()` method or `|` operator
|
||||
|
||||
4. **Transports** - Handle input/output for audio/video streams
|
||||
- WebRTC (Daily), WebSocket, Local audio, etc.
|
||||
- Located in: `src/pipecat/transports/`
|
||||
|
||||
### Key Directories
|
||||
|
||||
- `src/pipecat/` - Main source code
|
||||
- `frames/` - Frame definitions and utilities
|
||||
- `processors/` - Base processors and common processors
|
||||
- `services/` - AI service integrations (STT, TTS, LLM, etc.)
|
||||
- `transports/` - Transport implementations
|
||||
- `audio/` - Audio processing utilities
|
||||
- `examples/` - Example applications and foundational examples
|
||||
- `tests/` - Test suite
|
||||
- `docs/` - Documentation source
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
uv sync --group dev --all-extras --no-extra gstreamer --no-extra krisp --no-extra local
|
||||
|
||||
# Install pre-commit hooks
|
||||
uv run pre-commit install
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# All tests
|
||||
uv run pytest
|
||||
|
||||
# Specific test file
|
||||
uv run pytest tests/test_name.py
|
||||
|
||||
# With coverage
|
||||
uv run coverage run --module pytest
|
||||
uv run coverage report
|
||||
```
|
||||
|
||||
### Code Quality
|
||||
|
||||
```bash
|
||||
# Format code
|
||||
uv run ruff format .
|
||||
|
||||
# Lint code
|
||||
uv run ruff check .
|
||||
|
||||
# Fix linting issues
|
||||
uv run ruff check --fix .
|
||||
|
||||
# Type checking
|
||||
uv run pyright
|
||||
|
||||
# Run all pre-commit hooks
|
||||
uv run pre-commit run --all-files
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
```bash
|
||||
# Build package
|
||||
uv build
|
||||
```
|
||||
|
||||
## Custom Skills
|
||||
|
||||
This project includes custom Claude Code skills:
|
||||
|
||||
### `/docstring`
|
||||
Document Python modules and classes using Google-style docstrings.
|
||||
|
||||
Usage: `/docstring ClassName`
|
||||
|
||||
### `/changelog`
|
||||
Generate changelog entries using towncrier.
|
||||
|
||||
### `/pr-description`
|
||||
Generate comprehensive PR descriptions based on changes.
|
||||
|
||||
## Coding Standards
|
||||
|
||||
1. **Docstrings** - Use Google-style docstrings for all public APIs
|
||||
- Module docstrings required
|
||||
- Class docstrings with purpose and event handlers
|
||||
- Method docstrings with Args/Returns/Raises
|
||||
- Constructor (`__init__`) must document all parameters
|
||||
|
||||
2. **Type Hints** - Required for all function signatures
|
||||
- Use `from typing import ...` for complex types
|
||||
- Dataclasses should have field type annotations
|
||||
|
||||
3. **Async/Await** - Consistent use of async patterns
|
||||
- Most processors use async methods
|
||||
- Tests use pytest-asyncio
|
||||
|
||||
4. **Code Style**
|
||||
- Line length: 100 characters max
|
||||
- Ruff for linting and formatting
|
||||
- Follow existing patterns in the codebase
|
||||
|
||||
5. **Testing**
|
||||
- Write tests for new features
|
||||
- Use pytest fixtures for common setups
|
||||
- Mock external services when appropriate
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make changes following coding standards
|
||||
4. Add tests for new functionality
|
||||
5. Run pre-commit hooks: `uv run pre-commit run --all-files`
|
||||
6. Submit a pull request
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Adding a New Service Integration
|
||||
|
||||
1. Create service file in `src/pipecat/services/<category>/`
|
||||
2. Inherit from appropriate base class (e.g., `TTSService`, `LLMService`)
|
||||
3. Implement required abstract methods
|
||||
4. Add service to `pyproject.toml` optional dependencies
|
||||
5. Add documentation
|
||||
6. Add tests in `tests/`
|
||||
|
||||
### Adding a New Processor
|
||||
|
||||
1. Create processor in `src/pipecat/processors/`
|
||||
2. Inherit from `FrameProcessor` or appropriate subclass
|
||||
3. Override `process_frame()` method
|
||||
4. Handle relevant frame types
|
||||
5. Emit frames using `await self.push_frame()`
|
||||
6. Add tests
|
||||
|
||||
### Adding a New Frame Type
|
||||
|
||||
1. Add frame definition to `src/pipecat/frames/frames.py`
|
||||
2. Inherit from appropriate base frame class
|
||||
3. Use `@dataclass` decorator for data frames
|
||||
4. Document the frame type and its fields
|
||||
5. Update processors that should handle this frame type
|
||||
|
||||
## Resources
|
||||
|
||||
- [Documentation](https://docs.pipecat.ai)
|
||||
- [GitHub Repository](https://github.com/pipecat-ai/pipecat)
|
||||
- [Examples](https://github.com/pipecat-ai/pipecat-examples)
|
||||
- [Discord Community](https://discord.gg/pipecat)
|
||||
81
.claude/settings.json
Normal file
81
.claude/settings.json
Normal file
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"description": "Pipecat - Open-source Python framework for real-time voice and multimodal AI agents",
|
||||
"conventions": {
|
||||
"language": "Python",
|
||||
"version": ">=3.10",
|
||||
"package_manager": "uv",
|
||||
"code_style": "Google docstrings, Ruff formatting",
|
||||
"test_framework": "pytest",
|
||||
"async": true
|
||||
},
|
||||
"project_info": {
|
||||
"type": "python_library",
|
||||
"framework": "pipecat",
|
||||
"main_source": "src/pipecat",
|
||||
"examples": "examples/",
|
||||
"tests": "tests/",
|
||||
"docs": "docs/"
|
||||
},
|
||||
"commands": {
|
||||
"install": "uv sync --group dev --all-extras --no-extra gstreamer --no-extra krisp --no-extra local",
|
||||
"test": "uv run pytest",
|
||||
"test_file": "uv run pytest {file}",
|
||||
"lint": "uv run ruff check .",
|
||||
"lint_fix": "uv run ruff check --fix .",
|
||||
"format": "uv run ruff format .",
|
||||
"format_check": "uv run ruff format --check .",
|
||||
"type_check": "uv run pyright",
|
||||
"pre_commit": "uv run pre-commit run --all-files",
|
||||
"build": "uv build",
|
||||
"changelog": "uv run towncrier build --version {version}"
|
||||
},
|
||||
"coding_standards": [
|
||||
"Use Google-style docstrings for all public classes and methods",
|
||||
"Follow Ruff linting rules (see pyproject.toml)",
|
||||
"Maintain type hints for all function signatures",
|
||||
"Use async/await patterns consistently",
|
||||
"Keep line length at 100 characters maximum",
|
||||
"Use dataclasses with type annotations for configuration classes",
|
||||
"Prefer composition over inheritance where appropriate",
|
||||
"Write comprehensive pytest tests with asyncio support",
|
||||
"Document event handlers in class docstrings with Example:: sections"
|
||||
],
|
||||
"file_patterns": {
|
||||
"source_files": "src/pipecat/**/*.py",
|
||||
"test_files": "tests/**/*.py",
|
||||
"example_files": "examples/**/*.py",
|
||||
"config_files": "pyproject.toml"
|
||||
},
|
||||
"important_files": [
|
||||
"pyproject.toml - Project configuration and dependencies",
|
||||
"CONTRIBUTING.md - Contributing guidelines",
|
||||
"README.md - Project overview and quick start",
|
||||
"src/pipecat/__init__.py - Main package exports",
|
||||
"src/pipecat/frames/frames.py - Core frame definitions",
|
||||
"src/pipecat/processors/frame_processor.py - Base processor class"
|
||||
],
|
||||
"documentation": {
|
||||
"style": "Google",
|
||||
"build_command": "cd docs && make html",
|
||||
"skip_private_methods": true,
|
||||
"skip_simple_dunders": true,
|
||||
"require_module_docstrings": true,
|
||||
"require_class_docstrings": true,
|
||||
"require_init_docstrings": true
|
||||
},
|
||||
"git": {
|
||||
"main_branch": "main",
|
||||
"commit_style": "Conventional Commits",
|
||||
"pre_commit_hooks": true
|
||||
},
|
||||
"ai_assistance_notes": [
|
||||
"This project is a real-time voice and multimodal AI framework",
|
||||
"Core concepts: Frames (data units), Processors (processing units), Pipelines (chains of processors)",
|
||||
"Heavy use of async/await for real-time processing",
|
||||
"WebRTC and WebSocket transports for audio/video streaming",
|
||||
"Integration with many AI services (OpenAI, Anthropic, Deepgram, ElevenLabs, etc.)",
|
||||
"Frame-based architecture allows composable, modular pipeline construction",
|
||||
"Tests use pytest-asyncio for async test support",
|
||||
"Pre-commit hooks enforce code quality (run 'uv run pre-commit install')"
|
||||
]
|
||||
}
|
||||
40
.claude/skills/changelog/SKILL.md
Normal file
40
.claude/skills/changelog/SKILL.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: changelog
|
||||
description: Create changelog files for important commits in a PR
|
||||
---
|
||||
|
||||
Create changelog files for the important commits in this PR. The PR number is provided as an argument.
|
||||
|
||||
## Instructions
|
||||
|
||||
1. First, check what commits are on the current branch compared to main:
|
||||
```
|
||||
git log main..HEAD --oneline
|
||||
```
|
||||
|
||||
2. For each significant change, create a changelog file in the `changelog/` folder using the format:
|
||||
- `{PR_NUMBER}.added.md` - for new features
|
||||
- `{PR_NUMBER}.added.2.md`, `{PR_NUMBER}.added.3.md` - for additional new features
|
||||
- `{PR_NUMBER}.changed.md` - for changes to existing functionality
|
||||
- `{PR_NUMBER}.fixed.md` - for bug fixes
|
||||
- `{PR_NUMBER}.deprecated.md` - for deprecations
|
||||
|
||||
3. Each changelog file should at least contain a main single line starting with `- ` followed by a clear description of the change.
|
||||
|
||||
4. If the change is complicated, changelog files can have indented lines after the main line with additional details or code samples.
|
||||
|
||||
5. Use ⚠️ emoji prefix for breaking changes.
|
||||
|
||||
## Example
|
||||
|
||||
For PR #3519 with a new feature and a bug fix:
|
||||
|
||||
`changelog/3519.added.md`:
|
||||
```
|
||||
- Added `SomeNewFeature` for doing something useful.
|
||||
```
|
||||
|
||||
`changelog/3519.fixed.md`:
|
||||
```
|
||||
- Fixed an issue where something was not working correctly.
|
||||
```
|
||||
257
.claude/skills/docstring/SKILL.md
Normal file
257
.claude/skills/docstring/SKILL.md
Normal file
@@ -0,0 +1,257 @@
|
||||
---
|
||||
name: docstring
|
||||
description: Document a Python module and its classes using Google style
|
||||
---
|
||||
|
||||
Document a Python module and its classes using Google-style docstrings following project conventions. The class name is provided as an argument.
|
||||
|
||||
## Instructions
|
||||
|
||||
1. First, find the class in the codebase:
|
||||
```
|
||||
Search for "class ClassName" in src/pipecat/
|
||||
```
|
||||
|
||||
2. If multiple files contain that class name:
|
||||
- List all matches with their file paths
|
||||
- Ask the user which one they want to document
|
||||
- Wait for confirmation before proceeding
|
||||
|
||||
3. Once the file is identified, read the module to understand its structure:
|
||||
- Identify all classes, functions, and important type aliases
|
||||
- Understand the purpose of each component
|
||||
|
||||
4. Apply documentation in this order:
|
||||
- Module docstring (at top, after imports)
|
||||
- Class docstrings
|
||||
- `__init__` methods (always document constructor parameters)
|
||||
- Public methods (not starting with `_`)
|
||||
- Dataclass/config classes with field descriptions
|
||||
|
||||
5. Skip documentation for:
|
||||
- Private methods (starting with `_`)
|
||||
- Simple dunder methods (`__str__`, `__repr__`, `__post_init__`)
|
||||
- Very simple pass-through properties
|
||||
- **Already documented code** - If a class, method, or function already has a complete docstring that follows the project style, do not modify it. A docstring is complete if it has:
|
||||
- A one-line summary
|
||||
- Args section (if it has parameters)
|
||||
- Returns section (if it returns something meaningful)
|
||||
- Only add or improve documentation where it is missing or incomplete
|
||||
|
||||
## Module Docstring Format
|
||||
|
||||
```python
|
||||
"""[One-line description of module purpose].
|
||||
|
||||
[Optional: Longer explanation of functionality, key classes, or use cases.]
|
||||
"""
|
||||
```
|
||||
|
||||
Example:
|
||||
```python
|
||||
"""Neuphonic text-to-speech service implementations.
|
||||
|
||||
This module provides WebSocket and HTTP-based integrations with Neuphonic's
|
||||
text-to-speech API for real-time audio synthesis.
|
||||
"""
|
||||
```
|
||||
|
||||
## Class Docstring Format
|
||||
|
||||
```python
|
||||
class ClassName:
|
||||
"""One-line summary describing what the class does.
|
||||
|
||||
[Longer description explaining purpose, behavior, and key features.
|
||||
Use action-oriented language.]
|
||||
|
||||
[Optional: Event handlers, usage notes, or important caveats.]
|
||||
"""
|
||||
```
|
||||
|
||||
Example:
|
||||
```python
|
||||
class FrameProcessor(BaseObject):
|
||||
"""Base class for all frame processors in the pipeline.
|
||||
|
||||
Frame processors are the building blocks of Pipecat pipelines, they can be
|
||||
linked to form complex processing pipelines. They receive frames, process
|
||||
them, and pass them to the next or previous processor in the chain.
|
||||
|
||||
Event handlers available:
|
||||
|
||||
- on_before_process_frame: Called before a frame is processed
|
||||
- on_after_process_frame: Called after a frame is processed
|
||||
|
||||
Example::
|
||||
|
||||
@processor.event_handler("on_before_process_frame")
|
||||
async def on_before_process_frame(processor, frame):
|
||||
...
|
||||
|
||||
@processor.event_handler("on_after_process_frame")
|
||||
async def on_after_process_frame(processor, frame):
|
||||
...
|
||||
"""
|
||||
```
|
||||
|
||||
Note: When listing event handlers, do NOT use backticks. Include an `Example::` section (with double colon for Sphinx) showing the decorator pattern and function signature for each event.
|
||||
|
||||
## Constructor (`__init__`) Format
|
||||
|
||||
```python
|
||||
def __init__(self, *, param1: Type, param2: Type = default, **kwargs):
|
||||
"""Initialize the [ClassName].
|
||||
|
||||
Args:
|
||||
param1: Description of param1 and its purpose.
|
||||
param2: Description of param2. Defaults to [default].
|
||||
**kwargs: Additional arguments passed to parent class.
|
||||
"""
|
||||
```
|
||||
|
||||
Example:
|
||||
```python
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
api_key: str,
|
||||
voice_id: Optional[str] = None,
|
||||
sample_rate: Optional[int] = 22050,
|
||||
**kwargs,
|
||||
):
|
||||
"""Initialize the Neuphonic TTS service.
|
||||
|
||||
Args:
|
||||
api_key: Neuphonic API key for authentication.
|
||||
voice_id: ID of the voice to use for synthesis.
|
||||
sample_rate: Audio sample rate in Hz. Defaults to 22050.
|
||||
**kwargs: Additional arguments passed to parent InterruptibleTTSService.
|
||||
"""
|
||||
```
|
||||
|
||||
## Method Docstring Format
|
||||
|
||||
```python
|
||||
async def method_name(self, param1: Type) -> ReturnType:
|
||||
"""One-line summary of what method does.
|
||||
|
||||
[Longer description if behavior isn't obvious.]
|
||||
|
||||
Args:
|
||||
param1: Description of param1.
|
||||
|
||||
Returns:
|
||||
Description of return value.
|
||||
|
||||
Raises:
|
||||
ExceptionType: When this exception is raised.
|
||||
"""
|
||||
```
|
||||
|
||||
Example:
|
||||
```python
|
||||
async def put(self, item: Tuple[Frame, FrameDirection, FrameCallback]):
|
||||
"""Put an item into the priority queue.
|
||||
|
||||
System frames (`SystemFrame`) have higher priority than any other
|
||||
frames. If a non-frame item is provided it will have the highest priority.
|
||||
|
||||
Args:
|
||||
item: The item to enqueue.
|
||||
"""
|
||||
```
|
||||
|
||||
## Dataclass/Config Format
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class ConfigName:
|
||||
"""One-line description of configuration.
|
||||
|
||||
[Explanation of when/how to use this config.]
|
||||
|
||||
Parameters:
|
||||
field1: Description of field1.
|
||||
field2: Description of field2. Defaults to [default].
|
||||
"""
|
||||
|
||||
field1: Type
|
||||
field2: Type = default_value
|
||||
```
|
||||
|
||||
Example:
|
||||
```python
|
||||
@dataclass
|
||||
class FrameProcessorSetup:
|
||||
"""Configuration parameters for frame processor initialization.
|
||||
|
||||
Parameters:
|
||||
clock: The clock instance for timing operations.
|
||||
task_manager: The task manager for handling async operations.
|
||||
observer: Optional observer for monitoring frame processing events.
|
||||
"""
|
||||
|
||||
clock: BaseClock
|
||||
task_manager: BaseTaskManager
|
||||
observer: Optional[BaseObserver] = None
|
||||
```
|
||||
|
||||
## Enum Documentation Format
|
||||
|
||||
```python
|
||||
class EnumName(Enum):
|
||||
"""One-line description of the enum purpose.
|
||||
|
||||
[Longer description of how the enum is used.]
|
||||
|
||||
Parameters:
|
||||
VALUE1: Description of VALUE1.
|
||||
VALUE2: Description of VALUE2.
|
||||
"""
|
||||
|
||||
VALUE1 = 1
|
||||
VALUE2 = 2
|
||||
```
|
||||
|
||||
## Writing Style Guidelines
|
||||
|
||||
- **Concise and professional** - No casual language or filler words
|
||||
- **Action-oriented** - Start with verbs: "Processes...", "Manages...", "Converts..."
|
||||
- **Purpose before implementation** - Explain WHY before HOW
|
||||
- **Clear parameter descriptions** - Include type hints, defaults, and purpose
|
||||
- **No redundant type info** - Type hints are in the signature, don't repeat in description
|
||||
- **Use backticks for code references** - Wrap class names, method names, event names, parameter names, and code snippets in backticks
|
||||
|
||||
Good: "Neuphonic API key for authentication."
|
||||
Bad: "str: The API key (string) that is used for authenticating with Neuphonic."
|
||||
|
||||
Good: "Triggers `on_speech_started` when the `VADAnalyzer` detects speech."
|
||||
Bad: "Triggers on_speech_started when the VADAnalyzer detects speech."
|
||||
|
||||
## Deprecation Notice Format
|
||||
|
||||
When documenting deprecated code:
|
||||
|
||||
```python
|
||||
"""[Description].
|
||||
|
||||
.. deprecated:: X.X.X
|
||||
`ClassName` is deprecated and will be removed in a future version.
|
||||
Use `NewClassName` instead.
|
||||
"""
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
Before finishing, verify:
|
||||
|
||||
- [ ] Module has a docstring at the top (after copyright header and imports)
|
||||
- [ ] All public classes have docstrings
|
||||
- [ ] All `__init__` methods document their parameters
|
||||
- [ ] All public methods have docstrings with Args/Returns/Raises as needed
|
||||
- [ ] Dataclasses use "Parameters:" section for field descriptions
|
||||
- [ ] Enums document each value in "Parameters:" section
|
||||
- [ ] Writing is concise and action-oriented
|
||||
- [ ] No documentation added to private methods (starting with `_`)
|
||||
- [ ] Existing complete docstrings were left unchanged
|
||||
128
.claude/skills/pr-description/SKILL.md
Normal file
128
.claude/skills/pr-description/SKILL.md
Normal file
@@ -0,0 +1,128 @@
|
||||
---
|
||||
name: pr-description
|
||||
description: Update a GitHub PR description with a summary of changes
|
||||
---
|
||||
|
||||
Update a GitHub pull request description based on the changes in the PR.
|
||||
|
||||
## Arguments
|
||||
|
||||
```
|
||||
/pr-description <PR_NUMBER> [--fixes <ISSUE_NUMBERS>]
|
||||
```
|
||||
|
||||
- `PR_NUMBER` (required): The pull request number to update
|
||||
- `--fixes` (optional): Comma-separated issue numbers that this PR fixes (e.g., `--fixes 123,456`)
|
||||
|
||||
Examples:
|
||||
- `/pr-description 3534`
|
||||
- `/pr-description 3534 --fixes 123`
|
||||
- `/pr-description 3534 --fixes 123,456,789`
|
||||
|
||||
## Instructions
|
||||
|
||||
1. First, gather information about the PR:
|
||||
- Use GitHub plugin to get PR details (title, current description, base branch)
|
||||
- Use local git to get commits: `git log main..HEAD --oneline`
|
||||
- Use local git to get the diff: `git diff main..HEAD`
|
||||
- Parse any `--fixes` argument for issue numbers
|
||||
|
||||
2. Check the existing PR description:
|
||||
- If it already has a complete, accurate description that reflects the changes, do nothing
|
||||
- If it's missing sections, incomplete, or outdated compared to the actual changes, proceed to update
|
||||
- If it only has the template placeholder text, generate a full description
|
||||
|
||||
3. Analyze the changes:
|
||||
- Understand the purpose of each commit
|
||||
- Identify any breaking changes (API changes, removed features, behavior changes)
|
||||
- Look for new features, bug fixes, refactoring, or documentation changes
|
||||
- Collect issue numbers from:
|
||||
- The `--fixes` argument (if provided)
|
||||
- Commit messages (patterns like "Fixes #123", "Closes #456", "Resolves #789")
|
||||
|
||||
4. Generate or update the PR description with these sections:
|
||||
|
||||
## PR Description Format
|
||||
|
||||
### Summary (always include)
|
||||
|
||||
Brief bullet points describing what changed and why. Focus on the *purpose* and *impact*, not implementation details.
|
||||
|
||||
```markdown
|
||||
## Summary
|
||||
|
||||
- Added X to enable Y
|
||||
- Fixed bug where Z would happen
|
||||
- Refactored W for better maintainability
|
||||
```
|
||||
|
||||
### Breaking Changes (include only if applicable)
|
||||
|
||||
Document any changes that affect existing users or APIs.
|
||||
|
||||
```markdown
|
||||
## Breaking Changes
|
||||
|
||||
- `ClassName.method()` now requires a `param` argument
|
||||
- Removed deprecated `old_function()` - use `new_function()` instead
|
||||
```
|
||||
|
||||
### Testing (include when non-obvious)
|
||||
|
||||
How to verify the changes work. Skip for trivial changes.
|
||||
|
||||
```markdown
|
||||
## Testing
|
||||
|
||||
- Run `uv run pytest tests/test_feature.py` to verify the fix
|
||||
- Example usage: `uv run examples/new_feature.py`
|
||||
```
|
||||
|
||||
### Fixes (include if issues are provided or found in commits)
|
||||
|
||||
List issues this PR fixes. GitHub will automatically close these issues when the PR is merged.
|
||||
|
||||
```markdown
|
||||
## Fixes
|
||||
|
||||
- Fixes #123
|
||||
- Fixes #456
|
||||
```
|
||||
|
||||
Note: Use "Fixes #X" format (not "Closes" or "Resolves") for consistency. Each issue should be on its own line with "Fixes" to ensure GitHub auto-closes them.
|
||||
|
||||
## Guidelines
|
||||
|
||||
- **Be concise** - Reviewers should understand the PR in 30 seconds
|
||||
- **Focus on why** - The diff shows *what* changed, explain *why*
|
||||
- **Skip empty sections** - Only include sections that have content
|
||||
- **Use bullet points** - Easier to scan than paragraphs
|
||||
- **Don't duplicate the diff** - Avoid listing every file or line changed
|
||||
|
||||
## Example Output
|
||||
|
||||
```markdown
|
||||
## Summary
|
||||
|
||||
- Added `/docstring` skill for documenting Python modules with Google-style docstrings
|
||||
- Skill finds classes by name and handles conflicts when multiple matches exist
|
||||
- Skips already-documented code to avoid unnecessary changes
|
||||
|
||||
## Testing
|
||||
|
||||
/docstring ClassName
|
||||
|
||||
## Fixes
|
||||
|
||||
- Fixes #123
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
Before updating the PR:
|
||||
|
||||
- [ ] Verified existing description needs updating (not already complete)
|
||||
- [ ] Summary accurately reflects the changes
|
||||
- [ ] Breaking changes are clearly documented (if any)
|
||||
- [ ] No unnecessary sections included
|
||||
- [ ] Description is concise and scannable
|
||||
2
.github/workflows/coverage.yaml
vendored
2
.github/workflows/coverage.yaml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
uv sync --group dev --extra anthropic --extra aws --extra google --extra langchain
|
||||
uv sync --group dev --extra anthropic --extra aws --extra google --extra langchain --extra livekit --extra websocket
|
||||
|
||||
- name: Run tests with coverage
|
||||
run: |
|
||||
|
||||
2
.github/workflows/tests.yaml
vendored
2
.github/workflows/tests.yaml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
uv sync --group dev --extra anthropic --extra aws --extra google --extra langchain
|
||||
uv sync --group dev --extra anthropic --extra aws --extra google --extra langchain --extra livekit --extra websocket
|
||||
|
||||
- name: Test with pytest
|
||||
run: |
|
||||
|
||||
21
.gitignore
vendored
21
.gitignore
vendored
@@ -4,7 +4,14 @@ __pycache__/
|
||||
*~
|
||||
venv
|
||||
.venv
|
||||
/.idea
|
||||
.idea
|
||||
.gradle
|
||||
.next
|
||||
next-env.d.ts
|
||||
local.properties
|
||||
*.log
|
||||
*.lock
|
||||
smart_turn_audio_log
|
||||
#*#
|
||||
|
||||
# Distribution / Packaging
|
||||
@@ -27,7 +34,7 @@ share/python-wheels/
|
||||
*.egg
|
||||
MANIFEST
|
||||
.DS_Store
|
||||
.env
|
||||
.env*
|
||||
fly.toml
|
||||
|
||||
# Examples
|
||||
@@ -51,4 +58,12 @@ docs/api/_build/
|
||||
docs/api/api
|
||||
|
||||
# uv
|
||||
.python-version
|
||||
.python-version
|
||||
|
||||
# Pipecat
|
||||
whisker_setup.py
|
||||
|
||||
# Claude Code - exclude temporary files but keep configuration
|
||||
.claude/.claude-cache/
|
||||
.claude/**/*.tmp
|
||||
.claude/**/*.log
|
||||
658
CHANGELOG.md
658
CHANGELOG.md
@@ -7,6 +7,664 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
<!-- towncrier release notes start -->
|
||||
|
||||
## [0.0.100] - 2026-01-20
|
||||
|
||||
### Added
|
||||
|
||||
- Added Hathora service to support Hathora-hosted TTS and STT models (only
|
||||
non-streaming)
|
||||
(PR [#3169](https://github.com/pipecat-ai/pipecat/pull/3169))
|
||||
|
||||
- Added `CambTTSService`, using Camb.ai's TTS integration with MARS models
|
||||
(mars-flash, mars-pro, mars-instruct) for high-quality text-to-speech
|
||||
synthesis.
|
||||
(PR [#3349](https://github.com/pipecat-ai/pipecat/pull/3349))
|
||||
|
||||
- Added the `additional_headers` param to `WebsocketClientParams`, allowing
|
||||
`WebsocketClientTransport` to send custom headers on connect, for cases such
|
||||
as authentication.
|
||||
(PR [#3461](https://github.com/pipecat-ai/pipecat/pull/3461))
|
||||
|
||||
- Added `UserIdleController` for detecting user idle state, integrated into
|
||||
`LLMUserAggregator` and `UserTurnProcessor` via optional `user_idle_timeout`
|
||||
parameter. Emits `on_user_turn_idle` event for application-level handling.
|
||||
Deprecated `UserIdleProcessor` in favor of the new compositional approach.
|
||||
(PR [#3482](https://github.com/pipecat-ai/pipecat/pull/3482))
|
||||
|
||||
- Added `on_user_mute_started` and `on_user_mute_stopped` event handlers to
|
||||
`LLMUserAggregator` for tracking user mute state changes.
|
||||
(PR [#3490](https://github.com/pipecat-ai/pipecat/pull/3490))
|
||||
|
||||
### Changed
|
||||
|
||||
- Enhanced interruption handling in `AsyncAITTSService` by supporting
|
||||
multi-context WebSocket sessions for more robust context management.
|
||||
(PR [#3287](https://github.com/pipecat-ai/pipecat/pull/3287))
|
||||
|
||||
- Throttle `UserSpeakingFrame` to broadcast at most every 200ms instead of on
|
||||
every audio chunk, reducing frame processing overhead during user speech.
|
||||
(PR [#3483](https://github.com/pipecat-ai/pipecat/pull/3483))
|
||||
|
||||
### Deprecated
|
||||
|
||||
- For consistency with other package names, we just deprecated
|
||||
`pipecat.turns.mute` (introduced in Pipecat 0.0.99) in favor of
|
||||
`pipecat.turns.user_mute`.
|
||||
(PR [#3479](https://github.com/pipecat-ai/pipecat/pull/3479))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Corrected TTFB metric calculation in `AsyncAIHttpTTSService`.
|
||||
(PR [#3287](https://github.com/pipecat-ai/pipecat/pull/3287))
|
||||
|
||||
- Fixed an issue where the "bot-llm-text" RTVI event would not fire for
|
||||
realtime (speech-to-speech) services:
|
||||
|
||||
- `AWSNovaSonicLLMService`
|
||||
- `GeminiLiveLLMService`
|
||||
- `OpenAIRealtimeLLMService`
|
||||
- `GrokRealtimeLLMService`
|
||||
|
||||
The issue was that these services weren't pushing `LLMTextFrame`s. Now
|
||||
they do.
|
||||
(PR [#3446](https://github.com/pipecat-ai/pipecat/pull/3446))
|
||||
|
||||
- Fixed an issue where `on_user_turn_stop_timeout` could fire while a user is
|
||||
talking when using `ExternalUserTurnStrategies`.
|
||||
(PR [#3454](https://github.com/pipecat-ai/pipecat/pull/3454))
|
||||
|
||||
- Fixed an issue where user turn start strategies were not being reset after a
|
||||
user turn started, causing incorrect strategy behavior.
|
||||
(PR [#3455](https://github.com/pipecat-ai/pipecat/pull/3455))
|
||||
|
||||
- Fixed `MinWordsUserTurnStartStrategy` to not aggregate transcriptions,
|
||||
preventing incorrect turn starts when words are spoken with pauses between
|
||||
them.
|
||||
(PR [#3462](https://github.com/pipecat-ai/pipecat/pull/3462))
|
||||
|
||||
- Fixed an issue where Grok Realtime would error out when running with
|
||||
SmallWebRTC transport.
|
||||
(PR [#3480](https://github.com/pipecat-ai/pipecat/pull/3480))
|
||||
|
||||
- Fixed a `Mem0MemoryService` issue where passing `async_mode: true` was
|
||||
causing an error. See
|
||||
https://docs.mem0.ai/platform/features/async-mode-default-change.
|
||||
(PR [#3484](https://github.com/pipecat-ai/pipecat/pull/3484))
|
||||
|
||||
- Fixed `AWSNovaSonicLLMService.reset_conversation()`, which would previously
|
||||
error out. Now it successfully reconnects and "rehydrates" from the context
|
||||
object.
|
||||
(PR [#3486](https://github.com/pipecat-ai/pipecat/pull/3486))
|
||||
|
||||
- Fixed `AzureTTSService` transcript formatting issues:
|
||||
- Punctuation now appears without extra spaces (e.g., "Hello!" instead of
|
||||
"Hello !")
|
||||
- CJK languages (Chinese, Japanese, Korean) no longer have unwanted spaces
|
||||
between characters
|
||||
(PR [#3489](https://github.com/pipecat-ai/pipecat/pull/3489))
|
||||
|
||||
- Fixed an issue where `UninterruptibleFrame` frames would not be preserved in
|
||||
some cases.
|
||||
(PR [#3494](https://github.com/pipecat-ai/pipecat/pull/3494))
|
||||
|
||||
- Fixed memory leak in `LiveKitTransport` when `video_in_enabled` is `False`.
|
||||
(PR [#3499](https://github.com/pipecat-ai/pipecat/pull/3499))
|
||||
|
||||
- Fixed an issue in `AIService` where unhandled exceptions in `start()`,
|
||||
`stop()`, or `cancel()` implementations would prevent `process_frame()` to
|
||||
continue and therefore `StartFrame`, `EndFrame`, or `CancelFrame` from being
|
||||
pushed downstream, causing the pipeline to not start or stop properly.
|
||||
(PR [#3503](https://github.com/pipecat-ai/pipecat/pull/3503))
|
||||
|
||||
- Moved `NVIDIATTSService` and `NVIDIASTTService` client initialization from
|
||||
constructor to `start()` for better error handling.
|
||||
(PR [#3504](https://github.com/pipecat-ai/pipecat/pull/3504))
|
||||
|
||||
- Optimized `NVIDIATTSService` to process incoming audio frames immediately.
|
||||
(PR [#3509](https://github.com/pipecat-ai/pipecat/pull/3509))
|
||||
|
||||
- Optimized `NVIDIASTTService` by removing unnecessary queue and task.
|
||||
(PR [#3509](https://github.com/pipecat-ai/pipecat/pull/3509))
|
||||
|
||||
- Fixed a `CambTTSService` issue where client was being initialized in the
|
||||
constructor which wouldn't allow for proper Pipeline error handling.
|
||||
(PR [#3511](https://github.com/pipecat-ai/pipecat/pull/3511))
|
||||
|
||||
## [0.0.99] - 2026-01-13
|
||||
|
||||
### Added
|
||||
|
||||
- Introducing user turn strategies. User turn strategies indicate when the user
|
||||
turn starts or stops. In conversational agents, these are often referred to
|
||||
as start/stop speaking or turn-taking plans or policies.
|
||||
|
||||
User turn start strategies indicate when the user starts speaking (e.g.
|
||||
using VAD events or when a user says one or more words).
|
||||
|
||||
User turn stop strategies indicate when the user stops speaking (e.g. using
|
||||
an end-of-turn detection model or by observing incoming transcriptions).
|
||||
|
||||
A list of strategies can be specified for both strategies; strategies are
|
||||
evaluated in order until one evaluates to true.
|
||||
|
||||
Available user turn start strategies:
|
||||
|
||||
- VADUserTurnStartStrategy
|
||||
- TranscriptionUserTurnStartStrategy
|
||||
- MinWordsUserTurnStartStrategy
|
||||
- ExternalUserTurnStartStrategy
|
||||
|
||||
Available user turn stop strategies:
|
||||
|
||||
- TranscriptionUserTurnStopStrategy
|
||||
- TurnAnalyzerUserTurnStopStrategy
|
||||
- ExternalUserTurnStopStrategy
|
||||
|
||||
The default strategies are:
|
||||
|
||||
- start: [VADUserTurnStartStrategy, TranscriptionUserTurnStartStrategy]
|
||||
- stop: [TranscriptionUserTurnStopStrategy]
|
||||
|
||||
Turn strategies are configured when setting up `LLMContextAggregatorPair`.
|
||||
For example:
|
||||
|
||||
```python
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
stop=[
|
||||
TurnAnalyzerUserTurnStopStrategy(turn_analyzer=LocalSmartTurnAnalyzerV3(params=SmartTurnParams())
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
In order to use the user turn strategies you must update to the new
|
||||
universal `LLMContext` and `LLMContextAggregatorPair`.
|
||||
(PR [#3045](https://github.com/pipecat-ai/pipecat/pull/3045))
|
||||
|
||||
- Added `RNNoiseFilter` for real-time noise suppression using RNNoise neural
|
||||
network via pyrnnoise library.
|
||||
(PR [#3205](https://github.com/pipecat-ai/pipecat/pull/3205))
|
||||
|
||||
- Added `GrokRealtimeLLMService` for xAI's Grok Voice Agent API with real-time
|
||||
voice conversations:
|
||||
|
||||
- Support for real-time audio streaming with WebSocket connection
|
||||
- Built-in server-side VAD (Voice Activity Detection)
|
||||
- Multiple voice options: Ara, Rex, Sal, Eve, Leo
|
||||
- Built-in tools support: web_search, x_search, file_search
|
||||
- Custom function calling with standard Pipecat tools schema
|
||||
- Configurable audio formats (PCM at 8kHz-48kHz)
|
||||
(PR [#3267](https://github.com/pipecat-ai/pipecat/pull/3267))
|
||||
|
||||
- Added an approximation of TTFB for Ultravox.
|
||||
(PR [#3268](https://github.com/pipecat-ai/pipecat/pull/3268))
|
||||
|
||||
- Added a new `AudioContextTTSService` to the TTS service base classes. The
|
||||
`AudioContextWordTTSService` now inherits from `AudioContextTTSService` and
|
||||
`WebsocketWordTTSService`.
|
||||
(PR [#3289](https://github.com/pipecat-ai/pipecat/pull/3289))
|
||||
|
||||
- `LLMUserAggregator` now exposes the following events:
|
||||
|
||||
- `on_user_turn_started`: triggered when a user turn starts
|
||||
- `on_user_turn_stopped`: triggered when a user turn ends
|
||||
- `on_user_turn_stop_timeout`: triggered when a user turn does not stop
|
||||
and times out
|
||||
(PR [#3291](https://github.com/pipecat-ai/pipecat/pull/3291))
|
||||
|
||||
- Introducing user mute strategies. User mute strategies indicate when user
|
||||
input should be muted based on the current system state.
|
||||
|
||||
In conversational agents, user mute strategies are used to prevent user
|
||||
input from interrupting bot speech, tool execution, or other critical system
|
||||
operations.
|
||||
|
||||
A list of strategies can be specified; all strategies are evaluated for
|
||||
every frame so that each strategy can maintain its internal state. A user
|
||||
frame is muted if any of the configured strategies indicates it should be
|
||||
muted.
|
||||
|
||||
Available user mute strategies:
|
||||
|
||||
- `FirstSpeechUserMuteStrategy`
|
||||
- `MuteUntilFirstBotCompleteUserMuteStrategy`
|
||||
- `AlwaysUserMuteStrategy`
|
||||
- `FunctionCallUserMuteStrategy`
|
||||
|
||||
User mute strategies replace the legacy `STTMuteFilter` and provide a more
|
||||
flexible and composable approach to muting user input.
|
||||
|
||||
User mute strategies are configured when setting up the
|
||||
`LLMContextAggregatorPair`. For example:
|
||||
|
||||
```python
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_mute_strategies=[
|
||||
FirstSpeechUserMuteStrategy(),
|
||||
]
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
In order to use user mute strategies you should update to the new universal
|
||||
`LLMContext` and `LLMContextAggregatorPair`.
|
||||
(PR [#3292](https://github.com/pipecat-ai/pipecat/pull/3292))
|
||||
|
||||
- Added `use_ssl` parameter to `NvidiaSTTService`, `NvidiaSegmentedSTTService`
|
||||
and `NvidiaTTSService`.
|
||||
(PR [#3300](https://github.com/pipecat-ai/pipecat/pull/3300))
|
||||
|
||||
- Added `enable_interruptions` constructor argument to all user turn
|
||||
strategies. This tells the `LLMUserAggregator` to push or not push an
|
||||
`InterruptionFrame`.
|
||||
(PR [#3316](https://github.com/pipecat-ai/pipecat/pull/3316))
|
||||
|
||||
- Added `split_sentences` parameter to `SpeechmaticsSTTService` to control
|
||||
sentence splitting behavior for finals on sentence boundaries.
|
||||
(PR [#3328](https://github.com/pipecat-ai/pipecat/pull/3328))
|
||||
|
||||
- Added word-level timestamp support to `AzureTTSService` for accurate
|
||||
text-to-audio synchronization.
|
||||
(PR [#3334](https://github.com/pipecat-ai/pipecat/pull/3334))
|
||||
|
||||
- Added `pronunciation_dict_id` parameter to `CartesiaTTSService.InputParams`
|
||||
and `CartesiaHttpTTSService.InputParams` to support Cartesia's pronunciation
|
||||
dictionary feature for custom pronunciations.
|
||||
(PR [#3346](https://github.com/pipecat-ai/pipecat/pull/3346))
|
||||
|
||||
- Added support for using the HeyGen LiveAvatar API with the `HeyGenTransport`
|
||||
(see https://www.liveavatar.com/).
|
||||
(PR [#3357](https://github.com/pipecat-ai/pipecat/pull/3357))
|
||||
|
||||
- Added image support to `OpenAIRealtimeLLMService` via `InputImageRawFrame`:
|
||||
|
||||
- New `start_video_paused` parameter to control initial video input state
|
||||
- New `video_frame_detail` parameter to set image processing quality
|
||||
("auto",
|
||||
"low", or "high"). This corresponds to OpenAI Realtime's `image_detail`
|
||||
parameter.
|
||||
- `set_video_input_paused()` method to pause/resume video input at runtime
|
||||
- `set_video_frame_detail()` method to adjust video frame quality
|
||||
dynamically
|
||||
- Automatic rate limiting (1 frame per second) to prevent API overload
|
||||
(PR [#3360](https://github.com/pipecat-ai/pipecat/pull/3360))
|
||||
|
||||
- Added `UserTurnProcessor`, a frame processor built on `UserTurnController`
|
||||
that pushes `UserStartedSpeakingFrame` and `UserStoppedSpeakingFrame` frames
|
||||
and interruptions based on the controller's user turn strategies.
|
||||
(PR [#3372](https://github.com/pipecat-ai/pipecat/pull/3372))
|
||||
|
||||
- Added `UserTurnController` to manage user turns. It emits
|
||||
`on_user_turn_started`, `on_user_turn_stopped`, and
|
||||
`on_user_turn_stop_timeout` events, and can be integrated into processors to
|
||||
detect and handle user turns. `LLMUserAggregator` and `UserTurnProcessor` are
|
||||
implemented using this controller.
|
||||
(PR [#3372](https://github.com/pipecat-ai/pipecat/pull/3372))
|
||||
|
||||
- Added `should_interrupt` property to `DeepgramFluxSTTService`,
|
||||
`DeepgramSTTService`, and `SpeechmaticsSTTService` to configure whether the
|
||||
bot should be interrupted when the external service detects user speech.
|
||||
(PR [#3374](https://github.com/pipecat-ai/pipecat/pull/3374))
|
||||
|
||||
- `LLMAssistantAggregator` now exposes the following events:
|
||||
|
||||
- `on_assistant_turn_started`: triggered when the assistant turn starts
|
||||
- `on_assistant_turn_stopped`: triggered when the assistant turn ends
|
||||
- `on_assistant_thought`: triggered when there's an assistant thought
|
||||
available
|
||||
(PR [#3385](https://github.com/pipecat-ai/pipecat/pull/3385))
|
||||
|
||||
- Added `KrispVivaTurn` analyzer for end of turn detection using the Krisp VIVA
|
||||
SDK (requires `krisp_audio`).
|
||||
(PR [#3391](https://github.com/pipecat-ai/pipecat/pull/3391))
|
||||
|
||||
- Added support for setting up a pipeline task from external files. You can now
|
||||
register custom pipeline task setup files by setting the
|
||||
`PIPECAT_SETUP_FILES` environment variable. This variable should contain a
|
||||
colon-separated list of Python files (e.g. `export
|
||||
PIPECAT_SETUP_FILES="setup1.py:setup.py:..."`). Each file must define a
|
||||
function with the following signature:
|
||||
|
||||
```python
|
||||
async def setup_pipeline_task(task: PipelineTask):
|
||||
...
|
||||
```
|
||||
|
||||
(PR [#3397](https://github.com/pipecat-ai/pipecat/pull/3397))
|
||||
|
||||
- Added a keepalive task for `InworldTTSService` to keep the service connected
|
||||
in the event of no generations for longer periods of time.
|
||||
(PR [#3403](https://github.com/pipecat-ai/pipecat/pull/3403))
|
||||
|
||||
- Added `enable_vad` to `Params` for use in the `GladiaSTTService`. When
|
||||
enabled, `GladiaSTTService` acts as the turn controller, emitting
|
||||
`UserStartedSpeakingFrame`, `UserStoppedSpeakingFrame`, and optionally
|
||||
`InterruptionFrame`.
|
||||
(PR [#3404](https://github.com/pipecat-ai/pipecat/pull/3404))
|
||||
|
||||
- Added `should_interrupt` property to `GladiaSTTService` to configure whether
|
||||
the bot should be interrupted when the external service detects user speech.
|
||||
(PR [#3404](https://github.com/pipecat-ai/pipecat/pull/3404))
|
||||
|
||||
- Added `VonageFrameSerializer` for the Vonage Video API Audio Connector
|
||||
WebSocket protocol.
|
||||
(PR [#3410](https://github.com/pipecat-ai/pipecat/pull/3410))
|
||||
|
||||
- Added `append_trailing_space` parameter to `TTSService` to automatically
|
||||
append a trailing space to text before sending to TTS, helping prevent some
|
||||
services from vocalizing trailing punctuation.
|
||||
(PR [#3424](https://github.com/pipecat-ai/pipecat/pull/3424))
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated `ElevenLabsRealtimeSTTService` to accept the
|
||||
`include_language_detection` parameter to detect language.
|
||||
|
||||
```python
|
||||
stt = ElevenLabsRealtimeSTTService(
|
||||
api_key=os.getenv("ELEVENLABS_API_KEY"),
|
||||
include_language_detection=True
|
||||
)
|
||||
```
|
||||
|
||||
(PR [#3216](https://github.com/pipecat-ai/pipecat/pull/3216))
|
||||
|
||||
- Updated `SpeechmaticsSTTService` to use new Python Voice SDK with improved
|
||||
VAD, Smart Turn capabilities, and brings dramatic improvements to latency
|
||||
without any impact on accuracy. Use the `turn_detection_mode` parameter to control
|
||||
the endpointing of speech, with `TurnDetectionMode.EXTERNAL` (default),
|
||||
`TurnDetectionMode.ADAPTIVE`, or `TurnDetectionMode.SMART_TURN`.
|
||||
|
||||
```python
|
||||
stt = SpeechmaticsSTTService(
|
||||
api_key=os.getenv("SPEECHMATICS_API_KEY"),
|
||||
params=SpeechmaticsSTTService.InputParams(
|
||||
language=Language.EN,
|
||||
turn_detection_mode=SpeechmaticsSTTService.TurnDetectionMode.ADAPTIVE,
|
||||
speaker_active_format="<{speaker_id}>{text}</{speaker_id}>",
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
(PR [#3225](https://github.com/pipecat-ai/pipecat/pull/3225))
|
||||
|
||||
- `daily-python` updated to 0.23.0.
|
||||
(PR [#3257](https://github.com/pipecat-ai/pipecat/pull/3257))
|
||||
|
||||
- `TranscriptionFrame` and `InterimTranscriptionFrame` produced by
|
||||
`DailyTransport` now include the transport source (i.e., the originating
|
||||
audio track).
|
||||
(PR [#3257](https://github.com/pipecat-ai/pipecat/pull/3257))
|
||||
|
||||
- Updates to Inworld TTS services:
|
||||
|
||||
- Improved `InworldTTSService`'s websocket implementation to better flush
|
||||
and close context to better handle long inputs.
|
||||
- Improved docstrings for `InworldTTSService` and `InworldHttpTTSService`.
|
||||
(PR [#3288](https://github.com/pipecat-ai/pipecat/pull/3288))
|
||||
|
||||
- Improved the error handling and reconnection logic for `WebsocketServer` by
|
||||
distinguishing between errors when disconnecting and websocket communication
|
||||
errors.
|
||||
(PR [#3392](https://github.com/pipecat-ai/pipecat/pull/3392))
|
||||
|
||||
- Updated `DeepgramSTTService` to push user started/stopped speaking and
|
||||
interruption frames when `vad_enabled` is set to true. This centralizes the
|
||||
frames into the service, removing the need to have your application code
|
||||
handle Deepgram's events and push these frames.
|
||||
(PR [#3314](https://github.com/pipecat-ai/pipecat/pull/3314))
|
||||
|
||||
- Added encoding validation to `DeepgramTTSService` to prevent unsupported
|
||||
encodings from reaching the API. The service now raises `ValueError` at
|
||||
initialization with a clear error message.
|
||||
(PR [#3329](https://github.com/pipecat-ai/pipecat/pull/3329))
|
||||
|
||||
- Updated `read_audio_frame` & `read_video_frame` methods in
|
||||
`SmallWebRTCClient` to check if the track is enabled before logging a
|
||||
warning.
|
||||
(PR [#3336](https://github.com/pipecat-ai/pipecat/pull/3336))
|
||||
|
||||
- Updated `CartesiaTTSService` to support setting `language=None`, resulting in
|
||||
Cartesia auto-detecting the language of the conversation.
|
||||
(PR [#3366](https://github.com/pipecat-ai/pipecat/pull/3366))
|
||||
|
||||
- The bundled Smart Turn weights are now updated to v3.2, which has better
|
||||
handling of short utterances, and is more robust against background noise.
|
||||
(PR [#3367](https://github.com/pipecat-ai/pipecat/pull/3367))
|
||||
|
||||
- Updated `SpeechmaticsSTTService` dependency to `speechmatics-voice[smart]>=0.2.6`
|
||||
(PR [#3371](https://github.com/pipecat-ai/pipecat/pull/3371))
|
||||
|
||||
- Smart Turn now takes into account `vad_start_seconds` when buffering audio,
|
||||
meaning that the start of the turn audio is not cut off. This improves
|
||||
accuracy for short utterances.
|
||||
|
||||
- The default value of `pre_speech_ms` is now set to 500ms for Smart Turn.
|
||||
(PR [#3377](https://github.com/pipecat-ai/pipecat/pull/3377))
|
||||
|
||||
- Improved Krisp SDK management to allow `KrispVivaTurn` and `KrispVivaFilter`
|
||||
to share a single SDK instance within the same process.
|
||||
(PR [#3391](https://github.com/pipecat-ai/pipecat/pull/3391))
|
||||
|
||||
- Updated default model for `GroqTTSService` to `canopylabs/orpheus-v1-english`
|
||||
and voice ID to `autumn`.
|
||||
(PR [#3399](https://github.com/pipecat-ai/pipecat/pull/3399))
|
||||
|
||||
- Enhanced `FastAPIWebsocketTransport` with optional protocol-level audio
|
||||
packetization via the `fixed_audio_packet_size` parameter to support media
|
||||
endpoints requiring strict framing and real-time pacing.
|
||||
(PR [#3410](https://github.com/pipecat-ai/pipecat/pull/3410))
|
||||
|
||||
- `DeepgramTTSService` and `RimeTTSService` now set `append_trailing_space` to
|
||||
`True` to prevent punctuation (e.g., “dot”) from being pronounced.
|
||||
(PR [#3424](https://github.com/pipecat-ai/pipecat/pull/3424))
|
||||
|
||||
- Updated `GeminiLiveLLMService` to push `LLMThoughtStartFrame`,
|
||||
`LLMThoughtTextFrame`, and `LLMThoughtEndFrame` when the model returns
|
||||
thought content.
|
||||
(PR [#3431](https://github.com/pipecat-ai/pipecat/pull/3431))
|
||||
|
||||
### Deprecated
|
||||
|
||||
- `pipecat.audio.interruptions.MinWordsInterruptionStrategy` is deprecated. Use
|
||||
`pipecat.turns.user_start.MinWordsUserTurnStartStrategy` with
|
||||
`LLMUserAggregator`'s new `user_turn_strategies` parameter instead.
|
||||
(PR [#3045](https://github.com/pipecat-ai/pipecat/pull/3045))
|
||||
|
||||
- `FrameProcessor.interruption_strategies` is deprecated, use
|
||||
`LLMUserAggregator`'s new `user_turn_strategies` parameter instead.
|
||||
(PR [#3045](https://github.com/pipecat-ai/pipecat/pull/3045))
|
||||
|
||||
- The `LLMUserAggregatorParams` and `LLMAssistantAggregatorParams` classes in
|
||||
`pipecat.processors.aggregators.llm_response` are now deprecated. Use the new
|
||||
universal `LLMContext` and `LLMContextAggregatorPair` instead.
|
||||
(PR [#3045](https://github.com/pipecat-ai/pipecat/pull/3045))
|
||||
|
||||
- Deprecated the `emulated` field in the `UserStartedSpeakingFrame` and
|
||||
`UserStoppedSpeakingFrame` frames.
|
||||
(PR [#3045](https://github.com/pipecat-ai/pipecat/pull/3045))
|
||||
|
||||
- `EmulateUserStartedSpeakingFrame` and `EmulateUserStoppedSpeakingFrame`
|
||||
frames are deprecated.
|
||||
(PR [#3045](https://github.com/pipecat-ai/pipecat/pull/3045))
|
||||
|
||||
- ⚠️ `TransportParams.turn_analyzer` is deprecated and might result in
|
||||
unexpected behavior, use `LLMUserAggregator`'s new `user_turn_strategies`
|
||||
parameter instead.
|
||||
(PR [#3045](https://github.com/pipecat-ai/pipecat/pull/3045))
|
||||
|
||||
- For `SpeechmaticsSTTService`, the `end_of_utterance_mode` parameter is
|
||||
deprecated. Use the new `turn_detection_mode` parameter instead, with
|
||||
`TurnDetectionMode.EXTERNAL`,`TurnDetectionMode.ADAPTIVE`, or
|
||||
`TurnDetectionMode.SMART_TURN`. The `enable_vad` parameter is also
|
||||
deprecated and is inferred from the `turn_detection_mode`.
|
||||
(PR [#3225](https://github.com/pipecat-ai/pipecat/pull/3225))
|
||||
|
||||
- `OpenAILLMContext` and its associated things (context aggregators, etc.) are
|
||||
now deprecated in favor of the universal `LLMContext` and its associated
|
||||
things.
|
||||
|
||||
From the developer's point of view, switching to using `LLMContext`
|
||||
machinery will usually be a matter of going from this:
|
||||
|
||||
```python
|
||||
context = OpenAILLMContext(messages, tools)
|
||||
context_aggregator = llm.create_context_aggregator(context)
|
||||
```
|
||||
|
||||
To this:
|
||||
|
||||
```
|
||||
context = LLMContext(messages, tools)
|
||||
context_aggregator = LLMContextAggregatorPair(context)
|
||||
```
|
||||
|
||||
(PR [#3263](https://github.com/pipecat-ai/pipecat/pull/3263))
|
||||
|
||||
- `STTMuteFilter` is deprecated and will be removed in a future version. Use
|
||||
`LLMUserAggregator`'s new `user_mute_strategies` instead.
|
||||
(PR [#3292](https://github.com/pipecat-ai/pipecat/pull/3292))
|
||||
|
||||
- `FrameProcessor.interruptions_allowed` is now deprecated, use
|
||||
`LLMUserAggregator`'s new parameter `user_mute_strategies` instead.
|
||||
(PR [#3297](https://github.com/pipecat-ai/pipecat/pull/3297))
|
||||
|
||||
- `PipelineParams.allow_interruptions` is now deprecated, use
|
||||
`LLMUserAggregator`'s new parameter `user_turn_strategies` instead. For
|
||||
example, to disable interruptions but still get user turns you can do:
|
||||
|
||||
```python
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
start=[TranscriptionUserTurnStartStrategy(enable_interruptions=False)],
|
||||
),
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
(PR [#3297](https://github.com/pipecat-ai/pipecat/pull/3297))
|
||||
|
||||
- `TranscriptProcessor` and related data classes and frames
|
||||
(`TranscriptionMessage`, `ThoughtTranscriptionMessage`,
|
||||
`TranscriptionUpdateFrame`) are deprecated. Use `LLMUserAggregator`'s and
|
||||
`LLMAssistantAggregator`'s new events (`on_user_turn_stopped` and
|
||||
`on_assistant_turn_stopped`) instead.
|
||||
(PR [#3385](https://github.com/pipecat-ai/pipecat/pull/3385))
|
||||
|
||||
- Deprecated support for the `vad_events` `LiveOptions` in
|
||||
`DeepgramSTTService`. Instead, use a local Silero VAD for VAD events.
|
||||
Additionally, deprecated `should_interrupt` which will be removed along with
|
||||
`vad_events` support in a future release.
|
||||
(PR [#3386](https://github.com/pipecat-ai/pipecat/pull/3386))
|
||||
|
||||
- Loading external observers from files is deprecated, use the new pipeline
|
||||
task setup files and `PIPECAT_SETUP_FILES` environment variable instead.
|
||||
(PR [#3397](https://github.com/pipecat-ai/pipecat/pull/3397))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Improved error handling in `ElevenLabsRealtimeSTTService`
|
||||
(PR [#3233](https://github.com/pipecat-ai/pipecat/pull/3233))
|
||||
|
||||
- Fixed an issue in `ElevenLabsRealtimeSTTService` causing an infinite loop
|
||||
that blocks the process if the websocket disconnects due to an error
|
||||
(PR [#3233](https://github.com/pipecat-ai/pipecat/pull/3233))
|
||||
|
||||
- Fixed a bug in `STTMuteFilter` where the user was not always muted during
|
||||
function calls, especially when there were multiple simultaneous calls.
|
||||
(PR [#3292](https://github.com/pipecat-ai/pipecat/pull/3292))
|
||||
|
||||
- Fixed a `RNNoiseFilter` issue that would cause a "[Errno 12] Cannot allocate
|
||||
memory" error when processing silence audio frames.
|
||||
(PR [#3322](https://github.com/pipecat-ai/pipecat/pull/3322))
|
||||
|
||||
- Updated `SpeechmaticsSTTService` for version `0.0.99+`:
|
||||
|
||||
- Fixed `SpeechmaticsSTTService` to listen for `VADUserStoppedSpeakingFrame`
|
||||
in order to finalize transcription.
|
||||
- Default to `TurnDetectionMode.FIXED` for Pipecat-controlled end of turn
|
||||
detection.
|
||||
- Only emit VAD + interruption frames if VAD is enabled within the plugin
|
||||
(modes other than `TurnDetectionMode.FIXED` or `TurnDetectionMode.EXTERNAL`).
|
||||
(PR [#3328](https://github.com/pipecat-ai/pipecat/pull/3328))
|
||||
|
||||
- Fixed an issue with function calling where a handler failing to invoke its
|
||||
result callback could leave the context stuck in IN_PROGRESS, causing LLM
|
||||
inference for subsequent function call results to block while waiting on the
|
||||
unresolved call.
|
||||
(PR [#3343](https://github.com/pipecat-ai/pipecat/pull/3343))
|
||||
|
||||
- Fixed an issue with DeepgramTTSService where the model would output "Dot"
|
||||
instead of a period in some circumstances.
|
||||
(PR [#3345](https://github.com/pipecat-ai/pipecat/pull/3345))
|
||||
|
||||
- Fixed an issue in `traced_stt` where `model_name` in OpenTelemetry appears as
|
||||
`unknown`.
|
||||
(PR [#3351](https://github.com/pipecat-ai/pipecat/pull/3351))
|
||||
|
||||
- Fixed an issue in GeminiLiveLLMService where TranscriptionFrames were
|
||||
occasionally not pushed.
|
||||
(PR [#3356](https://github.com/pipecat-ai/pipecat/pull/3356))
|
||||
|
||||
- Fixed potential memory leaks and initialization issues in `KrispVivaFilter`
|
||||
by improving SDK lifecycle management.
|
||||
(PR [#3391](https://github.com/pipecat-ai/pipecat/pull/3391))
|
||||
|
||||
- Fixed timing issue in `BaseOutputTransport` where the bot speaking flag was
|
||||
set after awaiting, allowing the event loop to re-enter the method before the
|
||||
guard was set.
|
||||
(PR [#3400](https://github.com/pipecat-ai/pipecat/pull/3400))
|
||||
|
||||
- Fixed parallel function calling when using Gemini thinking.
|
||||
(PR [3420](https://github.com/pipecat-ai/pipecat/pull/3420))
|
||||
|
||||
- Fixed an issue in `traced_llm` where `model_name` in OpenTelemetry appears as
|
||||
`unknown`.
|
||||
(PR [#3422](https://github.com/pipecat-ai/pipecat/pull/3422))
|
||||
|
||||
- Fixed an issue in `traced_tts`, `traced_gemini_live`, and
|
||||
`traced_openai_realtime` where `model_name` in OpenTelemetry appears as
|
||||
`unknown`.
|
||||
(PR [#3428](https://github.com/pipecat-ai/pipecat/pull/3428))
|
||||
|
||||
- Fixed `request_image_frame` (for backwards compatibility) and restored
|
||||
function-call–related fields in `UserImageRequestFrame` and
|
||||
`UserImageRawFrame`, preventing a case where adding a non-LLM message to the
|
||||
context could trigger duplicate LLM inferences (on image arrival and on
|
||||
function-call result), potentially causing an infinite inference loop.
|
||||
(PR [#3430](https://github.com/pipecat-ai/pipecat/pull/3430))
|
||||
|
||||
- Fixed `LLMContext.create_audio_message()` by correcting an internal helper
|
||||
that was incorrectly declared async while being run in `asyncio.to_thread()`.
|
||||
(PR [#3435](https://github.com/pipecat-ai/pipecat/pull/3435))
|
||||
|
||||
### Other
|
||||
|
||||
- Added `52-live-transcription.py` foundational example demonstrating live
|
||||
transcription and translation from English to Spanish. In this example, the
|
||||
bot is not interruptible: as the user continues speaking, English
|
||||
transcriptions are queued, and the bot continuously translates and speaks
|
||||
each queued sentence in Spanish without being interrupted by new user speech.
|
||||
(PR [#3316](https://github.com/pipecat-ai/pipecat/pull/3316))
|
||||
|
||||
- Added a new foundational example `53-concurrent-llm-evaluation.py` that shows
|
||||
how to use `UserTurnProcessor`.
|
||||
(PR [#3372](https://github.com/pipecat-ai/pipecat/pull/3372))
|
||||
|
||||
- Added a new foundational example `28-user-assistant-turns.py` that shows how
|
||||
to use the new `LLMUserAggregator` and `LLMAssistantAggregator` events to
|
||||
gather a conversation transcript.
|
||||
(PR [#3385](https://github.com/pipecat-ai/pipecat/pull/3385))
|
||||
|
||||
## [0.0.98] - 2025-12-17
|
||||
|
||||
### Added
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2024–2025, Daily
|
||||
Copyright (c) 2024–2026, Daily
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
@@ -73,15 +73,15 @@ Catch new features, interviews, and how-tos on our [Pipecat TV](https://www.yout
|
||||
|
||||
| Category | Services |
|
||||
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Speech-to-Text | [AssemblyAI](https://docs.pipecat.ai/server/services/stt/assemblyai), [AWS](https://docs.pipecat.ai/server/services/stt/aws), [Azure](https://docs.pipecat.ai/server/services/stt/azure), [Cartesia](https://docs.pipecat.ai/server/services/stt/cartesia), [Deepgram](https://docs.pipecat.ai/server/services/stt/deepgram), [ElevenLabs](https://docs.pipecat.ai/server/services/stt/elevenlabs), [Fal Wizper](https://docs.pipecat.ai/server/services/stt/fal), [Gladia](https://docs.pipecat.ai/server/services/stt/gladia), [Google](https://docs.pipecat.ai/server/services/stt/google), [Gradium](https://docs.pipecat.ai/server/services/stt/gradium), [Groq (Whisper)](https://docs.pipecat.ai/server/services/stt/groq), [NVIDIA Riva](https://docs.pipecat.ai/server/services/stt/riva), [OpenAI (Whisper)](https://docs.pipecat.ai/server/services/stt/openai), [SambaNova (Whisper)](https://docs.pipecat.ai/server/services/stt/sambanova), [Sarvam](https://docs.pipecat.ai/server/services/stt/sarvam), [Soniox](https://docs.pipecat.ai/server/services/stt/soniox), [Speechmatics](https://docs.pipecat.ai/server/services/stt/speechmatics), [Whisper](https://docs.pipecat.ai/server/services/stt/whisper) |
|
||||
| Speech-to-Text | [AssemblyAI](https://docs.pipecat.ai/server/services/stt/assemblyai), [AWS](https://docs.pipecat.ai/server/services/stt/aws), [Azure](https://docs.pipecat.ai/server/services/stt/azure), [Cartesia](https://docs.pipecat.ai/server/services/stt/cartesia), [Deepgram](https://docs.pipecat.ai/server/services/stt/deepgram), [ElevenLabs](https://docs.pipecat.ai/server/services/stt/elevenlabs), [Fal Wizper](https://docs.pipecat.ai/server/services/stt/fal), [Gladia](https://docs.pipecat.ai/server/services/stt/gladia), [Google](https://docs.pipecat.ai/server/services/stt/google), [Gradium](https://docs.pipecat.ai/server/services/stt/gradium), [Groq (Whisper)](https://docs.pipecat.ai/server/services/stt/groq), [Hathora](https://docs.pipecat.ai/server/services/stt/hathora), [NVIDIA Riva](https://docs.pipecat.ai/server/services/stt/riva), [OpenAI (Whisper)](https://docs.pipecat.ai/server/services/stt/openai), [SambaNova (Whisper)](https://docs.pipecat.ai/server/services/stt/sambanova), [Sarvam](https://docs.pipecat.ai/server/services/stt/sarvam), [Soniox](https://docs.pipecat.ai/server/services/stt/soniox), [Speechmatics](https://docs.pipecat.ai/server/services/stt/speechmatics), [Whisper](https://docs.pipecat.ai/server/services/stt/whisper) |
|
||||
| LLMs | [Anthropic](https://docs.pipecat.ai/server/services/llm/anthropic), [AWS](https://docs.pipecat.ai/server/services/llm/aws), [Azure](https://docs.pipecat.ai/server/services/llm/azure), [Cerebras](https://docs.pipecat.ai/server/services/llm/cerebras), [DeepSeek](https://docs.pipecat.ai/server/services/llm/deepseek), [Fireworks AI](https://docs.pipecat.ai/server/services/llm/fireworks), [Gemini](https://docs.pipecat.ai/server/services/llm/gemini), [Grok](https://docs.pipecat.ai/server/services/llm/grok), [Groq](https://docs.pipecat.ai/server/services/llm/groq), [Mistral](https://docs.pipecat.ai/server/services/llm/mistral), [NVIDIA NIM](https://docs.pipecat.ai/server/services/llm/nim), [Ollama](https://docs.pipecat.ai/server/services/llm/ollama), [OpenAI](https://docs.pipecat.ai/server/services/llm/openai), [OpenRouter](https://docs.pipecat.ai/server/services/llm/openrouter), [Perplexity](https://docs.pipecat.ai/server/services/llm/perplexity), [Qwen](https://docs.pipecat.ai/server/services/llm/qwen), [SambaNova](https://docs.pipecat.ai/server/services/llm/sambanova) [Together AI](https://docs.pipecat.ai/server/services/llm/together) |
|
||||
| Text-to-Speech | [Async](https://docs.pipecat.ai/server/services/tts/asyncai), [AWS](https://docs.pipecat.ai/server/services/tts/aws), [Azure](https://docs.pipecat.ai/server/services/tts/azure), [Cartesia](https://docs.pipecat.ai/server/services/tts/cartesia), [Deepgram](https://docs.pipecat.ai/server/services/tts/deepgram), [ElevenLabs](https://docs.pipecat.ai/server/services/tts/elevenlabs), [Fish](https://docs.pipecat.ai/server/services/tts/fish), [Google](https://docs.pipecat.ai/server/services/tts/google), [Gradium](https://docs.pipecat.ai/server/services/tts/gradium), [Groq](https://docs.pipecat.ai/server/services/tts/groq), [Hume](https://docs.pipecat.ai/server/services/tts/hume), [Inworld](https://docs.pipecat.ai/server/services/tts/inworld), [LMNT](https://docs.pipecat.ai/server/services/tts/lmnt), [MiniMax](https://docs.pipecat.ai/server/services/tts/minimax), [Neuphonic](https://docs.pipecat.ai/server/services/tts/neuphonic), [NVIDIA Riva](https://docs.pipecat.ai/server/services/tts/riva), [OpenAI](https://docs.pipecat.ai/server/services/tts/openai), [Piper](https://docs.pipecat.ai/server/services/tts/piper), [PlayHT](https://docs.pipecat.ai/server/services/tts/playht), [Rime](https://docs.pipecat.ai/server/services/tts/rime), [Sarvam](https://docs.pipecat.ai/server/services/tts/sarvam), [Speechmatics](https://docs.pipecat.ai/server/services/tts/speechmatics), [XTTS](https://docs.pipecat.ai/server/services/tts/xtts) |
|
||||
| Text-to-Speech | [Async](https://docs.pipecat.ai/server/services/tts/asyncai), [AWS](https://docs.pipecat.ai/server/services/tts/aws), [Azure](https://docs.pipecat.ai/server/services/tts/azure), [Camb AI](https://docs.pipecat.ai/server/services/tts/camb), [Cartesia](https://docs.pipecat.ai/server/services/tts/cartesia), [Deepgram](https://docs.pipecat.ai/server/services/tts/deepgram), [ElevenLabs](https://docs.pipecat.ai/server/services/tts/elevenlabs), [Fish](https://docs.pipecat.ai/server/services/tts/fish), [Google](https://docs.pipecat.ai/server/services/tts/google), [Gradium](https://docs.pipecat.ai/server/services/tts/gradium), [Groq](https://docs.pipecat.ai/server/services/tts/groq), [Hathora](https://docs.pipecat.ai/server/services/tts/hathora), [Hume](https://docs.pipecat.ai/server/services/tts/hume), [Inworld](https://docs.pipecat.ai/server/services/tts/inworld), [LMNT](https://docs.pipecat.ai/server/services/tts/lmnt), [MiniMax](https://docs.pipecat.ai/server/services/tts/minimax), [Neuphonic](https://docs.pipecat.ai/server/services/tts/neuphonic), [NVIDIA Riva](https://docs.pipecat.ai/server/services/tts/riva), [OpenAI](https://docs.pipecat.ai/server/services/tts/openai), [Piper](https://docs.pipecat.ai/server/services/tts/piper), [PlayHT](https://docs.pipecat.ai/server/services/tts/playht), [Rime](https://docs.pipecat.ai/server/services/tts/rime), [Sarvam](https://docs.pipecat.ai/server/services/tts/sarvam), [Speechmatics](https://docs.pipecat.ai/server/services/tts/speechmatics), [XTTS](https://docs.pipecat.ai/server/services/tts/xtts) |
|
||||
| Speech-to-Speech | [AWS Nova Sonic](https://docs.pipecat.ai/server/services/s2s/aws), [Gemini Multimodal Live](https://docs.pipecat.ai/server/services/s2s/gemini), [Grok Voice Agent](https://docs.pipecat.ai/server/services/s2s/grok), [OpenAI Realtime](https://docs.pipecat.ai/server/services/s2s/openai), [Ultravox](https://docs.pipecat.ai/server/services/s2s/ultravox), |
|
||||
| Transport | [Daily (WebRTC)](https://docs.pipecat.ai/server/services/transport/daily), [FastAPI Websocket](https://docs.pipecat.ai/server/services/transport/fastapi-websocket), [SmallWebRTCTransport](https://docs.pipecat.ai/server/services/transport/small-webrtc), [WebSocket Server](https://docs.pipecat.ai/server/services/transport/websocket-server), Local |
|
||||
| Serializers | [Plivo](https://docs.pipecat.ai/server/utilities/serializers/plivo), [Twilio](https://docs.pipecat.ai/server/utilities/serializers/twilio), [Telnyx](https://docs.pipecat.ai/server/utilities/serializers/telnyx) |
|
||||
| Serializers | [Exotel](https://docs.pipecat.ai/server/utilities/serializers/exotel), [Plivo](https://docs.pipecat.ai/server/utilities/serializers/plivo), [Twilio](https://docs.pipecat.ai/server/utilities/serializers/twilio), [Telnyx](https://docs.pipecat.ai/server/utilities/serializers/telnyx), [Vonage](https://docs.pipecat.ai/server/utilities/serializers/vonage) |
|
||||
| Video | [HeyGen](https://docs.pipecat.ai/server/services/video/heygen), [Tavus](https://docs.pipecat.ai/server/services/video/tavus), [Simli](https://docs.pipecat.ai/server/services/video/simli) |
|
||||
| Memory | [mem0](https://docs.pipecat.ai/server/services/memory/mem0) |
|
||||
| Vision & Image | [fal](https://docs.pipecat.ai/server/services/image-generation/fal), [Google Imagen](https://docs.pipecat.ai/server/services/image-generation/fal), [Moondream](https://docs.pipecat.ai/server/services/vision/moondream) |
|
||||
| Vision & Image | [fal](https://docs.pipecat.ai/server/services/image-generation/fal), [Google Imagen](https://docs.pipecat.ai/server/services/image-generation/google-imagen), [Moondream](https://docs.pipecat.ai/server/services/vision/moondream) |
|
||||
| Audio Processing | [Silero VAD](https://docs.pipecat.ai/server/utilities/audio/silero-vad-analyzer), [Krisp](https://docs.pipecat.ai/server/utilities/audio/krisp-filter), [Koala](https://docs.pipecat.ai/server/utilities/audio/koala-filter), [ai-coustics](https://docs.pipecat.ai/server/utilities/audio/aic-filter) |
|
||||
| Analytics & Metrics | [OpenTelemetry](https://docs.pipecat.ai/server/utilities/opentelemetry), [Sentry](https://docs.pipecat.ai/server/services/analytics/sentry) |
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
- Introducing user turn strategies. User turn strategies indicate when the user turn starts or stops. In conversational agents, these are often referred to as start/stop speaking or turn-taking plans or policies.
|
||||
|
||||
User turn start strategies indicate when the user starts speaking (e.g. using VAD events or when a user says one or more words).
|
||||
|
||||
User turn stop strategies indicate when the user stops speaking (e.g. using an end-of-turn detection model or by observing incoming transcriptions).
|
||||
|
||||
A list of strategies can be specified for both strategies; strategies are evaluated in order until one evaluates to true.
|
||||
|
||||
Available user turn start strategies:
|
||||
- VADUserTurnStartStrategy
|
||||
- TranscriptionUserTurnStartStrategy
|
||||
- MinWordsUserTurnStartStrategy
|
||||
- ExternalUserTurnStartStrategy
|
||||
|
||||
Available user turn stop strategies:
|
||||
- TranscriptionUserTurnStopStrategy
|
||||
- TurnAnalyzerUserTurnStopStrategy
|
||||
- ExternalUserTurnStopStrategy
|
||||
|
||||
The default strategies are:
|
||||
|
||||
- start: [VADUserTurnStartStrategy, TranscriptionUserTurnStartStrategy]
|
||||
- stop: [TranscriptionUserTurnStopStrategy]
|
||||
|
||||
Turn strategies are configured when setting up `LLMContextAggregatorPair`. For example:
|
||||
|
||||
```python
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
stop=[
|
||||
TurnAnalyzerUserTurnStopStrategy(
|
||||
turn_analyzer=LocalSmartTurnAnalyzerV3(params=SmartTurnParams())
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
In order to use the user turn strategies you must update to the new universal `LLMContext` and `LLMContextAggregatorPair`.
|
||||
@@ -1 +0,0 @@
|
||||
- ⚠️ `TransportParams.turn_analyzer` is deprecated and might result in unexpected behavior, use `LLMUserAggregator`'s new `turn_start_strategies` parameter instead.
|
||||
@@ -1 +0,0 @@
|
||||
- `FrameProcessor.interruption_strategies` is deprecated, use `LLMUserAggregator`'s new `turn_start_strategies` parameter instead.
|
||||
@@ -1 +0,0 @@
|
||||
- `EmulateUserStartedSpeakingFrame` and `EmulateUserStoppedSpeakingFrame` frames are deprecated.
|
||||
@@ -1 +0,0 @@
|
||||
- Deprecated the `emulated` field in the `UserStartedSpeakingFrame` and `UserStoppedSpeakingFrame` frames.
|
||||
@@ -1 +0,0 @@
|
||||
- The `LLMUserAggregatorParams` and `LLMAssistantAggregatorParams` classes in `pipecat.processors.aggregators.llm_response` are now deprecated. Use the new universal `LLMContext` and `LLMContextAggregatorPair` instead.
|
||||
@@ -1 +0,0 @@
|
||||
- `pipecat.audio.interruptions.MinWordsInterruptionStrategy` is deprecated. Use `pipecat.turns.user_start.MinWordsUserTurnStartStrategy` with `LLMUserAggregator`'s new `turn_start_strategies` parameter instead.
|
||||
@@ -1 +0,0 @@
|
||||
- Added `RNNoiseFilter` for real-time noise suppression using RNNoise neural network via pyrnnoise library.
|
||||
@@ -1,15 +0,0 @@
|
||||
- Updated `SpeechmaticsSTTService` to use new Python Voice SDK with improved VAD,
|
||||
Smart Turn capabilities, and brings dramatic improvements to latency without
|
||||
any impact on accuracy. Use the `turn_detection_mode` parameter to control the
|
||||
endpointing of speech, with `TurnDetectionMode.EXTERNAL` (default),
|
||||
`TurnDetectionMode.ADAPTIVE`, or `TurnDetectionMode.SMART_TURN`.
|
||||
```python
|
||||
stt = SpeechmaticsSTTService(
|
||||
api_key=os.getenv("SPEECHMATICS_API_KEY"),
|
||||
params=SpeechmaticsSTTService.InputParams(
|
||||
language=Language.EN,
|
||||
turn_detection_mode=SpeechmaticsSTTService.TurnDetectionMode.ADAPTIVE,
|
||||
speaker_active_format="<{speaker_id}>{text}</{speaker_id}>",
|
||||
),
|
||||
)
|
||||
```
|
||||
@@ -1,4 +0,0 @@
|
||||
- For `SpeechmaticsSTTService`, the `end_of_utterance_mode` parameter is deprecated.
|
||||
Use the new `turn_detection_mode` parameter instead, with `TurnDetectionMode.EXTERNAL`,
|
||||
`TurnDetectionMode.ADAPTIVE`, or `TurnDetectionMode.SMART_TURN`. The `enable_vad`
|
||||
parameter is also deprecated and is inferred from the `turn_detection_mode`.
|
||||
@@ -1,2 +0,0 @@
|
||||
- Improved error handling in `ElevenLabsRealtimeSTTService`
|
||||
- Fixed an issue in `ElevenLabsRealtimeSTTService` causing an infinite loop that blocks the process if the websocket disconnects due to an error
|
||||
@@ -1 +0,0 @@
|
||||
- `TranscriptionFrame` and `InterimTranscriptionFrame` produced by `DailyTransport` now include the transport source (i.e., the originating audio track).
|
||||
@@ -1 +0,0 @@
|
||||
- `daily-python` updated to 0.23.0.
|
||||
@@ -1,15 +0,0 @@
|
||||
- `OpenAILLMContext` and its associated things (context aggregators, etc.) are now deprecated in favor of the universal `LLMContext` and its associated things.
|
||||
|
||||
From the developer's point of view, switching to using `LLMContext` machinery will usually be a matter of going from this:
|
||||
|
||||
```python
|
||||
context = OpenAILLMContext(messages, tools)
|
||||
context_aggregator = llm.create_context_aggregator(context)
|
||||
```
|
||||
|
||||
To this:
|
||||
|
||||
```
|
||||
context = LLMContext(messages, tools)
|
||||
context_aggregator = LLMContextAggregatorPair(context)
|
||||
```
|
||||
@@ -1,8 +0,0 @@
|
||||
- Added `GrokRealtimeLLMService` for xAI's Grok Voice Agent API with real-time voice conversations:
|
||||
|
||||
- Support for real-time audio streaming with WebSocket connection
|
||||
- Built-in server-side VAD (Voice Activity Detection)
|
||||
- Multiple voice options: Ara, Rex, Sal, Eve, Leo
|
||||
- Built-in tools support: web_search, x_search, file_search
|
||||
- Custom function calling with standard Pipecat tools schema
|
||||
- Configurable audio formats (PCM at 8kHz-48kHz)
|
||||
@@ -1 +0,0 @@
|
||||
- Added an approximation of TTFB for Ultravox.
|
||||
@@ -1,5 +0,0 @@
|
||||
- Updates to Inworld TTS services:
|
||||
|
||||
- Improved `InworldTTSService`'s websocket implementation to better flush and
|
||||
close context to better handle long inputs.
|
||||
- Improved docstrings for `InworldTTSService` and `InworldHttpTTSService`.
|
||||
@@ -1 +0,0 @@
|
||||
- Added a new `AudioContextTTSService` to the TTS service base classes. The `AudioContextWordTTSService` now inherits from `AudioContextTTSService` and `WebsocketWordTTSService`.
|
||||
@@ -1,4 +0,0 @@
|
||||
- `LLMUserAggregator` now exposes the following events:
|
||||
- `on_user_turn_started`: triggered when a user turn starts
|
||||
- `on_user_turn_stopped`: triggered when a user turn ends
|
||||
- `on_user_turn_stop_timeout`: triggered when a user turn does not stop and times out
|
||||
@@ -1,29 +0,0 @@
|
||||
- Introducing user mute strategies. User mute strategies indicate when user input should be muted based on the current system state.
|
||||
|
||||
In conversational agents, user mute strategies are used to prevent user input from interrupting bot speech, tool execution, or other critical system operations.
|
||||
|
||||
A list of strategies can be specified; all strategies are evaluated for every frame so that each strategy can maintain its internal state. A user frame is muted if any of the configured strategies indicates it should be muted.
|
||||
|
||||
Available user mute strategies:
|
||||
|
||||
* `FirstSpeechUserMuteStrategy`
|
||||
* `MuteUntilFirstBotCompleteUserMuteStrategy`
|
||||
* `AlwaysUserMuteStrategy`
|
||||
* `FunctionCallUserMuteStrategy`
|
||||
|
||||
User mute strategies replace the legacy `STTMuteFilter` and provide a more flexible and composable approach to muting user input.
|
||||
|
||||
User mute strategies are configured when setting up the `LLMContextAggregatorPair`. For example:
|
||||
|
||||
```python
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_mute_strategies=[
|
||||
FirstSpeechUserMuteStrategy(),
|
||||
]
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
In order to use user mute strategies you should update to the new universal `LLMContext` and `LLMContextAggregatorPair`.
|
||||
@@ -1 +0,0 @@
|
||||
- `STTMuteFilter` is deprecated and will be removed in a future version. Use `LLMUserAggregator`'s new `user_mute_strategies` instead.
|
||||
@@ -1 +0,0 @@
|
||||
- Fixed a bug in `STTMuteFilter` where the user was not always muted during function calls, especially when there were multiple simultaneous calls.
|
||||
@@ -1 +0,0 @@
|
||||
- `FrameProcessor.interruptions_allowed` is now deprecated, use `LLMUserAggregator`'s new parameter `user_mute_strategies` instead.
|
||||
@@ -1,12 +0,0 @@
|
||||
- `PipelineParams.allow_interruptions` is now deprecated, use `LLMUserAggregator`'s new parameter `turn_start_strategies` instead. For example, to disable interruptions but still get user turns you can do:
|
||||
|
||||
```python
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
start=[TranscriptionUserTurnStartStrategy(enable_interruptions=False)],
|
||||
),
|
||||
),
|
||||
)
|
||||
```
|
||||
@@ -1 +0,0 @@
|
||||
- Added `use_ssl` parameter to `NvidiaSTTService`, `NvidiaSegmentedSTTService` and `NvidiaTTSService`.
|
||||
@@ -1 +0,0 @@
|
||||
- Updated `DeepgramSTTService` to push user started/stopped speaking and interruption frames when `vad_enabled` is set to true. This centralizes the frames into the service, removing the need to have your application code handle Deepgram's events and push these frames.
|
||||
@@ -1 +0,0 @@
|
||||
- Added `enable_interruptions` constructor argument to all user turn strategies. This tells the `LLMUserAggregator` to push or not push an `InterruptionFrame`.
|
||||
@@ -1 +0,0 @@
|
||||
- Added `52-live-transcription.py` foundational example demonstrating live transcription and translation from English to Spanish. In this example, the bot is not interruptible: as the user continues speaking, English transcriptions are queued, and the bot continuously translates and speaks each queued sentence in Spanish without being interrupted by new user speech.
|
||||
@@ -1 +0,0 @@
|
||||
- Frame processors can now push frames from the top of the pipeline using new methods `queue_task_frame()` and `queue_task_frames()`.
|
||||
1
changelog/3406.fixed.md
Normal file
1
changelog/3406.fixed.md
Normal file
@@ -0,0 +1 @@
|
||||
- Fixed an issue where if you were using `OpenRouterLLMService` with a Gemini model, it wouldn't handle multiple `"system"` messages as expected (and as we do in `GoogleLLMService`), which is to convert subsequent ones into `"user"` messages. Instead, the latest `"system"` message would overwrite the previous ones.
|
||||
1
changelog/3495.changed.2.md
Normal file
1
changelog/3495.changed.2.md
Normal file
@@ -0,0 +1 @@
|
||||
- `SarvamSTTService` now defaults `vad_signals` and `high_vad_sensitivity` to `None` (omitted from connection parameters), improving latency by ~300ms compared to the previous defaults.
|
||||
1
changelog/3495.changed.md
Normal file
1
changelog/3495.changed.md
Normal file
@@ -0,0 +1 @@
|
||||
- Improved the STT TTFB (Time To First Byte) measurement, reporting the delay between when the user stops speaking and when the final transcription is received. Note: Unlike traditional TTFB which measures from a discrete request, STT services receive continuous audio input—so we measure from speech end to final transcript, which captures the latency that matters for voice AI applications. In support of this change, added `finalized` field to `TranscriptionFrame` to indicate when a transcript is the final result for an utterance.
|
||||
1
changelog/3510.added.2.md
Normal file
1
changelog/3510.added.2.md
Normal file
@@ -0,0 +1 @@
|
||||
- Added `add_reached_upstream_filter()` and `add_reached_downstream_filter()` methods to `PipelineTask` for appending frame types.
|
||||
1
changelog/3510.added.md
Normal file
1
changelog/3510.added.md
Normal file
@@ -0,0 +1 @@
|
||||
- Added `reached_upstream_types` and `reached_downstream_types` read-only properties to `PipelineTask` for inspecting current frame filters.
|
||||
1
changelog/3510.changed.3.md
Normal file
1
changelog/3510.changed.3.md
Normal file
@@ -0,0 +1 @@
|
||||
- Changed frame filter storage from tuples to sets in `PipelineTask`.
|
||||
1
changelog/3519.added.2.md
Normal file
1
changelog/3519.added.2.md
Normal file
@@ -0,0 +1 @@
|
||||
- Added `RTVIProcessor.create_rtvi_observer()` factory method for creating RTVI observers.
|
||||
1
changelog/3519.added.3.md
Normal file
1
changelog/3519.added.3.md
Normal file
@@ -0,0 +1 @@
|
||||
- Added `FrameProcessor.broadcast_frame_instance(frame)` method to broadcast a frame instance by extracting its fields and creating new instances for each direction.
|
||||
1
changelog/3519.added.md
Normal file
1
changelog/3519.added.md
Normal file
@@ -0,0 +1 @@
|
||||
- `PipelineTask` now automatically adds `RTVIProcessor` and registers `RTVIObserver` when `enable_rtvi=True` (default), simplifying pipeline setup.
|
||||
1
changelog/3519.fixed.2.md
Normal file
1
changelog/3519.fixed.2.md
Normal file
@@ -0,0 +1 @@
|
||||
- Fixed `FrameProcessor.broadcast_frame()` to deep copy kwargs, preventing shared mutable references between the downstream and upstream frame instances.
|
||||
1
changelog/3519.fixed.md
Normal file
1
changelog/3519.fixed.md
Normal file
@@ -0,0 +1 @@
|
||||
- Transports now properly broadcast `InputTransportMessageFrame` frames both upstream and downstream instead of only pushing downstream.
|
||||
1
changelog/3520.added.md
Normal file
1
changelog/3520.added.md
Normal file
@@ -0,0 +1 @@
|
||||
- Added `video_out_codec` parameter to `TransportParams` allowing configuration of the preferred video codec (e.g., `"VP8"`, `"H264"`, `"H265"`) for video output in `DailyTransport`.
|
||||
1
changelog/3523.added.md
Normal file
1
changelog/3523.added.md
Normal file
@@ -0,0 +1 @@
|
||||
- Added `location` parameter to Google TTS services (`GoogleHttpTTSService`, `GoogleTTSService`, `GeminiTTSService`) for regional endpoint support.
|
||||
1
changelog/3525.added.md
Normal file
1
changelog/3525.added.md
Normal file
@@ -0,0 +1 @@
|
||||
- Added new `PIPECAT_SMART_TURN_LOG_DATA` environment variable, which causes Smart Turn input data to be saved to disk
|
||||
2
changelog/3531.changed.md
Normal file
2
changelog/3531.changed.md
Normal file
@@ -0,0 +1,2 @@
|
||||
- Changed default Inworld TTS model from `inworld-tts-1` to
|
||||
`inworld-tts-1.5-max`.
|
||||
@@ -91,6 +91,25 @@ autodoc_mock_imports = [
|
||||
# MLX dependencies (Apple Silicon specific)
|
||||
"mlx",
|
||||
"mlx_whisper", # Note: might need underscore format too
|
||||
# Pydantic v2 compatibility issues in third-party SDKs
|
||||
"hume",
|
||||
"hume.tts",
|
||||
"hume.tts.types",
|
||||
"cartesia",
|
||||
"camb",
|
||||
"sarvamai",
|
||||
"openpipe",
|
||||
"openai.types.beta.realtime",
|
||||
"langchain_core",
|
||||
"langchain_core.messages",
|
||||
# FastAPI - Pydantic v2 compatibility issues during Sphinx autodoc
|
||||
"fastapi",
|
||||
"fastapi.applications",
|
||||
"fastapi.routing",
|
||||
"fastapi.params",
|
||||
"fastapi.middleware",
|
||||
"fastapi.responses",
|
||||
"uvicorn",
|
||||
]
|
||||
|
||||
# HTML output settings
|
||||
|
||||
@@ -31,6 +31,9 @@ AZURE_DALLE_API_KEY=...
|
||||
AZURE_DALLE_ENDPOINT=https://...
|
||||
AZURE_DALLE_MODEL=...
|
||||
|
||||
# Camb.ai
|
||||
CAMB_API_KEY=...
|
||||
|
||||
# Cartesia
|
||||
CARTESIA_API_KEY=...
|
||||
CARTESIA_VOICE_ID=...
|
||||
@@ -82,6 +85,9 @@ GROK_API_KEY=...
|
||||
# Groq
|
||||
GROQ_API_KEY=...
|
||||
|
||||
# Hathora
|
||||
HATHORA_API_KEY=...
|
||||
|
||||
# Heygen
|
||||
HEYGEN_API_KEY=...
|
||||
HEYGEN_LIVE_AVATAR_API_KEY=...
|
||||
@@ -97,7 +103,8 @@ INWORLD_API_KEY=...
|
||||
KRISP_MODEL_PATH=...
|
||||
|
||||
# Krisp Viva
|
||||
KRISP_VIVA_MODEL_PATH=...
|
||||
KRISP_VIVA_FILTER_MODEL_PATH=...
|
||||
KRISP_VIVA_TURN_MODEL_PATH=...
|
||||
|
||||
# LiveKit
|
||||
LIVEKIT_API_KEY=...
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -85,7 +85,7 @@ async def run_example(webrtc_connection: SmallWebRTCConnection):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -98,11 +98,11 @@ async def run_example(webrtc_connection: SmallWebRTCConnection):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -68,7 +68,7 @@ async def main():
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -82,11 +82,11 @@ async def main():
|
||||
pipeline = Pipeline(
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -78,7 +78,7 @@ async def main():
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -91,11 +91,11 @@ async def main():
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -106,7 +106,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -119,12 +119,12 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(),
|
||||
stt,
|
||||
context_aggregator.user(),
|
||||
user_aggregator,
|
||||
llm,
|
||||
tts,
|
||||
ml,
|
||||
transport.output(),
|
||||
context_aggregator.assistant(),
|
||||
assistant_aggregator,
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -120,7 +120,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -138,12 +138,12 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(),
|
||||
stt,
|
||||
context_aggregator.user(),
|
||||
user_aggregator,
|
||||
llm,
|
||||
tts,
|
||||
image_sync_aggregator,
|
||||
transport.output(),
|
||||
context_aggregator.assistant(),
|
||||
assistant_aggregator,
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -77,7 +77,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -90,11 +90,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -76,7 +76,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -89,11 +89,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -131,7 +131,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(user_turn_strategies=ExternalUserTurnStrategies()),
|
||||
)
|
||||
@@ -140,11 +140,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -117,7 +117,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -132,11 +132,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt, # STT
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -103,7 +103,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
lc = LangchainProcessor(history_chain)
|
||||
|
||||
context = LLMContext()
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -116,11 +116,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
lc, # Langchain
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -71,7 +71,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(user_turn_strategies=ExternalUserTurnStrategies()),
|
||||
)
|
||||
@@ -80,11 +80,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt, # STT
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -81,7 +81,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -96,11 +96,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt, # STT
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -86,7 +86,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -99,11 +99,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt, # STT
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -72,7 +72,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(user_turn_strategies=ExternalUserTurnStrategies()),
|
||||
)
|
||||
@@ -81,11 +81,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt, # STT
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -75,7 +75,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -88,11 +88,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt, # STT
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -85,7 +85,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -100,11 +100,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -78,7 +78,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -91,11 +91,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -78,7 +78,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -91,11 +91,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -80,7 +80,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -93,11 +93,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -84,7 +84,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -97,11 +97,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt, # STT
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -84,7 +84,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -97,11 +97,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt, # STT
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -78,7 +78,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -91,11 +91,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt, # STT
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -83,7 +83,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -96,11 +96,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -81,7 +81,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -96,11 +96,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
140
examples/foundational/07j-interruptible-gladia-vad.py
Normal file
140
examples/foundational/07j-interruptible-gladia-vad.py
Normal file
@@ -0,0 +1,140 @@
|
||||
#
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
|
||||
import os
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from loguru import logger
|
||||
|
||||
from pipecat.audio.vad.silero import SileroVADAnalyzer
|
||||
from pipecat.audio.vad.vad_analyzer import VADParams
|
||||
from pipecat.frames.frames import LLMRunFrame
|
||||
from pipecat.pipeline.pipeline import Pipeline
|
||||
from pipecat.pipeline.runner import PipelineRunner
|
||||
from pipecat.pipeline.task import PipelineParams, PipelineTask
|
||||
from pipecat.processors.aggregators.llm_context import LLMContext
|
||||
from pipecat.processors.aggregators.llm_response_universal import (
|
||||
LLMContextAggregatorPair,
|
||||
LLMUserAggregatorParams,
|
||||
)
|
||||
from pipecat.runner.types import RunnerArguments
|
||||
from pipecat.runner.utils import create_transport
|
||||
from pipecat.services.cartesia.tts import CartesiaTTSService
|
||||
from pipecat.services.gladia.config import GladiaInputParams, LanguageConfig
|
||||
from pipecat.services.gladia.stt import GladiaSTTService
|
||||
from pipecat.services.openai.llm import OpenAILLMService
|
||||
from pipecat.transcriptions.language import Language
|
||||
from pipecat.transports.base_transport import BaseTransport, TransportParams
|
||||
from pipecat.transports.daily.transport import DailyParams
|
||||
from pipecat.transports.websocket.fastapi import FastAPIWebsocketParams
|
||||
from pipecat.turns.user_turn_strategies import ExternalUserTurnStrategies
|
||||
|
||||
load_dotenv(override=True)
|
||||
|
||||
# We store functions so objects (e.g. SileroVADAnalyzer) don't get
|
||||
# instantiated. The function will be called when the desired transport gets
|
||||
# selected.
|
||||
transport_params = {
|
||||
"daily": lambda: DailyParams(
|
||||
audio_in_enabled=True,
|
||||
audio_out_enabled=True,
|
||||
vad_analyzer=SileroVADAnalyzer(params=VADParams(stop_secs=0.2)),
|
||||
),
|
||||
"twilio": lambda: FastAPIWebsocketParams(
|
||||
audio_in_enabled=True,
|
||||
audio_out_enabled=True,
|
||||
vad_analyzer=SileroVADAnalyzer(params=VADParams(stop_secs=0.2)),
|
||||
),
|
||||
"webrtc": lambda: TransportParams(
|
||||
audio_in_enabled=True,
|
||||
audio_out_enabled=True,
|
||||
vad_analyzer=SileroVADAnalyzer(params=VADParams(stop_secs=0.2)),
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
logger.info(f"Starting bot")
|
||||
|
||||
stt = GladiaSTTService(
|
||||
api_key=os.getenv("GLADIA_API_KEY", ""),
|
||||
region=os.getenv("GLADIA_REGION"),
|
||||
params=GladiaInputParams(
|
||||
language_config=LanguageConfig(
|
||||
languages=[Language.EN],
|
||||
),
|
||||
enable_vad=True,
|
||||
),
|
||||
)
|
||||
|
||||
tts = CartesiaTTSService(
|
||||
api_key=os.getenv("CARTESIA_API_KEY", ""),
|
||||
voice_id="71a7ad14-091c-4e8e-a314-022ece01c121", # British Reading Lady
|
||||
)
|
||||
|
||||
llm = OpenAILLMService(api_key=os.getenv("OPENAI_API_KEY", ""))
|
||||
|
||||
messages = [
|
||||
{
|
||||
"role": "system",
|
||||
"content": f"You are a helpful LLM. Your goal is to demonstrate your capabilities in a succinct way. Your output will be spoken aloud, so avoid special characters that can't easily be spoken, such as emojis or bullet points. Respond to what the user said in a creative and helpful way.",
|
||||
},
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(user_turn_strategies=ExternalUserTurnStrategies()),
|
||||
)
|
||||
|
||||
pipeline = Pipeline(
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt, # STT
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
task = PipelineTask(
|
||||
pipeline,
|
||||
params=PipelineParams(
|
||||
enable_metrics=True,
|
||||
enable_usage_metrics=True,
|
||||
),
|
||||
idle_timeout_secs=runner_args.pipeline_idle_timeout_secs,
|
||||
)
|
||||
|
||||
@transport.event_handler("on_client_connected")
|
||||
async def on_client_connected(transport, client):
|
||||
logger.info(f"Client connected")
|
||||
# Kick off the conversation.
|
||||
messages.append({"role": "system", "content": "Please introduce yourself to the user."})
|
||||
await task.queue_frames([LLMRunFrame()])
|
||||
|
||||
@transport.event_handler("on_client_disconnected")
|
||||
async def on_client_disconnected(transport, client):
|
||||
logger.info(f"Client disconnected")
|
||||
await task.cancel()
|
||||
|
||||
runner = PipelineRunner(handle_sigint=runner_args.handle_sigint)
|
||||
await runner.run(task)
|
||||
|
||||
|
||||
async def bot(runner_args: RunnerArguments):
|
||||
"""Main bot entry point compatible with Pipecat Cloud."""
|
||||
transport = await create_transport(runner_args, transport_params)
|
||||
await run_bot(transport, runner_args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from pipecat.runner.run import main
|
||||
|
||||
main()
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -87,7 +87,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -100,11 +100,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt, # STT
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -10,7 +10,6 @@ import os
|
||||
from dotenv import load_dotenv
|
||||
from loguru import logger
|
||||
|
||||
from pipecat.audio.turn.smart_turn.base_smart_turn import SmartTurnParams
|
||||
from pipecat.audio.turn.smart_turn.local_smart_turn_v3 import LocalSmartTurnAnalyzerV3
|
||||
from pipecat.audio.vad.silero import SileroVADAnalyzer
|
||||
from pipecat.audio.vad.vad_analyzer import VADParams
|
||||
@@ -75,7 +74,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -88,11 +87,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User respones
|
||||
user_aggregator, # User respones
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -76,7 +76,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
]
|
||||
|
||||
context = LLMContext(messages)
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -89,11 +89,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt,
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
# Copyright (c) 2024-2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
@@ -120,7 +120,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
|
||||
# Setup context aggregators for message handling
|
||||
context = LLMContext()
|
||||
context_aggregator = LLMContextAggregatorPair(
|
||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||
context,
|
||||
user_params=LLMUserAggregatorParams(
|
||||
user_turn_strategies=UserTurnStrategies(
|
||||
@@ -133,11 +133,11 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt, # Speech-to-text
|
||||
context_aggregator.user(), # User responses
|
||||
user_aggregator, # User responses
|
||||
llm, # Strands Agents processor
|
||||
tts, # Text-to-speech
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
assistant_aggregator, # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user