Merge pull request #1 from dograh-hq/dev

fix storage_backend value and docker image versions
This commit is contained in:
Sabiha Khan 2025-09-10 11:22:51 +05:30 committed by GitHub
commit abaa750dea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 289 additions and 37 deletions

64
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,64 @@
# Contributing to Dograh AI
First off — thank you for considering contributing! 🎉
Dograh AI is open source because we believe the future of voice AI should stay in the hands of developers and the community.
For now, this guide will get you started. Future documentation will be more comprehensive and is under progress.
👉 Join us → [Dograh Community Slack](https://join.slack.com/t/dograh-community/shared_invite/zt-3czr47sw5-MSg1J0kJ7IMPOCHF~03auQ)
## 🙌 How You Can Contribute
- 🐛 **Report bugs** via GitHub Issues
- 💡 **Suggest features**
- 🔧 **Submit pull requests**
- 📖 **Improve documentation** — even fixing typos helps!
- 💬 **Join the Slack community** — the cornerstone of our collaboration
## 🧰 Issue Types
On our [GitHub Issues page](../../issues), youll find these categories:
- 📄 **Documentation change request**
- ✨ **Feature request**
- 🐞 **Bug report**
- ❓ **General questions**
- 🔒 **Security vulnerability report**
👉 A great place to start is with issues tagged **`good first issue`**.
## 🛠 Development Guidelines
- Keep PRs focused and scoped.
- Follow Python best practices (PEP8).
- Please **link the issue** in your PR description using: fixes #<issue_number>
This auto-closes the issue when merged.
## 🚀 Getting Started
- Fork the repository
- Create your feature branch (git checkout -b feature/AmazingFeature)
- Commit your changes (git commit -m 'Add some AmazingFeature')
- Push to the branch (git push origin feature/AmazingFeature)
Open a Pull Request 🎉
## 💬 Community & Contribution Hub
Our Slack community is not just for support — its the cornerstone of Dograh AI contributions. Here, you can:
- Connect with maintainers and other contributors
- Discuss issues and features before coding
- Get help with setup and debugging
- Stay up to date with contribution sprints
👉 Join us → [Dograh Community Slack](https://join.slack.com/t/dograh-community/shared_invite/zt-3czr47sw5-MSg1J0kJ7IMPOCHF~03auQ)
Thank you for helping us keep Dograh AI open and thriving! 💜

24
LICENSE Normal file
View file

@ -0,0 +1,24 @@
BSD 2-Clause License
Copyright (c) 2025, Zansat Technologies Private Limited
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

158
README.md Normal file
View file

@ -0,0 +1,158 @@
# Dograh AI
<p align="center">
<a href="LICENSE">
<img src="https://img.shields.io/badge/license-BSD%202--Clause-blue.svg" alt="License: BSD 2-Clause">
</a>
<a href="https://join.slack.com/t/dograh-community/shared_invite/zt-3czr47sw5-MSg1J0kJ7IMPOCHF~03auQ">
<img src="https://img.shields.io/badge/chat-on%20Slack-4A154B?logo=slack" alt="Slack Community">
</a>
<a href="https://www.docker.com/">
<img src="https://img.shields.io/badge/docker-ready-blue?logo=docker" alt="Docker Ready">
</a>
</p>
The fastest way to build voice bots - get started with any voice AI use case in under 2 minutes (our hard SLA standards).
Build voice agents in just one line or drag-and-drop, then test them using AI personas that mimic real customer calls. It's 100% open source, self-hosted if you want, and never hides a line of code- ever. The project has a strong commitment to **100% open source** and every line of code is released in the open.
Maintained by YC alumni and exit founders, we're making sure the future of voice AI stays open, not monopolized.
## 🎥 Demo Video
📺 [Watch 1-min demo video](#) *(coming soon)*
## 🚀 Quickstart
### Prerequisites
To run Dograh AI locally, make sure you have the following installed:
- [Docker](https://docs.docker.com/get-docker/)
- [Docker Compose](https://docs.docker.com/compose/install/)
- [curl](https://curl.se/download.html) usually preinstalled on macOS/Linux
> **Note**
> Make sure Docker Desktop (or your systems Docker service) is running before you begin.
## 🚀 Get Started
The only commands you need to run:
```bash
curl -o docker-compose.yml https://raw.githubusercontent.com/Flagsmith/flagsmith/main/docker-compose.yml
docker-compose -f docker-compose.yml up
````
> **Note**
> Open your browser at http://localhost:3000 and create your first AI voice assistant for the usecase you want!
### 🎙️ Your First Voice Bot
1. **Open Dashboard**: Launch [http://localhost:3000](http://localhost:3000) on your browser
2. **Choose Call Type**: Select **Inbound** or **Outbound** calling.
3. **Name Your Bot**: Use a short two-word name (e.g., *Lead Qualification*).
4. **Describe Use Case**: In 510 words (e.g., *Screen insurance form submissions for purchase intent*).
5. **Launch**: Your bot is ready! Open the bot and click **Web Call** to talk to it.
6. **No API Keys Needed**: We auto-generate Dograh API keys so you can start immediately. You can switch to your own keys anytime.
7. **Default Access**: Includes Dograhs own LLMs, STT, and TTS stack by default.
8. **Bring Your Own Keys**: Optionally connect your own API keys for LLMs, STT, TTS, or telephony providers like Twilio.
## Quick Summary
⚡ 2-Minute Setup: Hard SLA standards - from zero to working voice bot in under 2 minutes
- 🔧 Minimal setup: Just [run docker command](#get-started) and you're live
- 🤖 AI Testing Personas: Test your bots with LoopTalk AI that mimics real customer interactions
- 🔓 100% Open Source: Every line of code is open - no hidden logic, no black boxes
- 🔄 Flexible Integration: Bring your own LLM, TTS, or STT - or use Dograhs APIs
- ☁️ Self-Host or Cloud: Run locally or use our hosted version at app.dograh.com
## Features
### Voice Capabilities
- Telephony: Built-in Twilio integration (easily add others)
- Languages: English support (expandable to other languages)
- Custom Models: Bring your own TTS/STT models
- Real-time Processing: Low-latency voice interactions
### Developer Experience
- Zero Config Start: Auto-generated API keys for instant testing
- Python-Based: Built on Python for easy customization
- Docker-First: Containerized for consistent deployments
- Modular Architecture: Swap components as needed
### Testing & Quality
- LoopTalk (Beta): Create AI personas to test your voice agents
- Workflow Testing: Test specific workflow IDs with automated calls
- Real-world Simulation: AI personas that mimic actual customer behavior
## Configuration
Dograh automatically generates API keys on first run, but you can use your own keys.
- OPENAI_API_KEY=your_key_here
- TWILIO_ACCOUNT_SID=your_sid_here
- TWILIO_AUTH_TOKEN=your_token_here
## Architecture
Architecture diagram *(coming soon)*
## Deployment Options
### Local Development
Refer [prerequisites](#Prerequisites) and [first steps](#get-started)
### Production (Self-Hosted)
Production guide coming soon. [Drop in a message](https://join.slack.com/t/dograh-community/shared_invite/zt-3czr47sw5-MSg1J0kJ7IMPOCHF~03auQ) for assistance.
### Cloud Version
Visit [https://www.dograh.com](https://www.dograh.com/) for our managed cloud offering.
## 📚Documentation
Full documentation is in progress. For now, this README will get you started.
## 🤝Community & Support
- GitHub Issues: Report bugs or request features
- Slack: Our Slack community is not just for support — its the cornerstone of Dograh AI contributions. Here, you can:
- Connect with maintainers and other contributors
- Discuss issues and features before coding
- Get help with setup and debugging
- Stay up to date with contribution sprints
👉 Join us → Dograh Community Slack
## Tech Stack
- FastAPI
- Pipecat
- LiveKit
- PostgreSQL
- Next.js
- XYFlow React
- Inbuilt Twilio integration
- Flexible back-end: switch to any LLM, TTS, or STT
## 🙌 Contributing
We love contributions! Dograh AI is 100% open source and we intend to keep it that way.
### Getting Started
- Fork the repository
- Create your feature branch (git checkout -b feature/AmazingFeature)
- Commit your changes (git commit -m 'Add some AmazingFeature')
- Push to the branch (git push origin feature/AmazingFeature)
- Open a Pull Request
## 📄 License
Dograh AI is licensed under the [BSD 2-Clause License](LICENSE)- the same license as projects that were used in building Dograh AI, ensuring compatibility and freedom to use, modify, and distribute.
## 🏢 About
Built with ❤️ by **Dograh** (Zansat Technologies Private Limited)
Founded by YC alumni and exit founders committed to keeping voice AI open and accessible to everyone.
<br><br><br>
<p align="center">
<a href="https://github.com/dograh-hq/dograh/stargazers">⭐ Star us on GitHub</a> |
<a href="https://www.dograh.com">☁️ Try Cloud Version</a> |
<a href="https://join.slack.com/t/dograh-community/shared_invite/zt-3czr47sw5-MSg1J0kJ7IMPOCHF~03auQ">💬 Join Slack</a>
</p>

View file

@ -14,6 +14,7 @@ from api.db.models import (
WorkflowModel,
WorkflowRunModel,
)
from api.enums import StorageBackend
from api.schemas.workflow import WorkflowRunResponseSchema
@ -67,6 +68,9 @@ class WorkflowRunClient(BaseDBClient):
)
current_def = current_def_result.scalars().first()
# Get the current storage backend based on ENABLE_AWS_S3 flag
current_backend = StorageBackend.get_current_backend()
new_run = WorkflowRunModel(
name=name,
workflow=workflow,
@ -75,6 +79,7 @@ class WorkflowRunClient(BaseDBClient):
initial_context=initial_context or workflow.template_context_variables,
campaign_id=campaign_id,
queued_run_id=queued_run_id,
storage_backend=current_backend.value,
)
session.add(new_run)
try:

View file

@ -1,9 +1,11 @@
import asyncio
from datetime import timedelta
from datetime import datetime, timedelta, timezone
from typing import Any, BinaryIO, Dict, Optional
from loguru import logger
from minio import Minio
from minio.error import S3Error
import json
from .base import BaseFileSystem
@ -42,12 +44,29 @@ class MinioFileSystem(BaseFileSystem):
endpoint, access_key=access_key, secret_key=secret_key, secure=secure
)
# Ensure bucket exists (using internal client)
# Ensure bucket exists and configure anonymous access (using internal client)
try:
if not self.client.bucket_exists(self.bucket_name):
self.client.make_bucket(self.bucket_name)
# Set anonymous download policy for local development
# This allows unsigned URLs to work
policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"AWS": "*"},
"Action": ["s3:GetObject"],
"Resource": [f"arn:aws:s3:::{self.bucket_name}/*"]
}
]
}
self.client.set_bucket_policy(self.bucket_name, json.dumps(policy))
except Exception as e:
# Bucket might already exist or we might be in a restricted environment
logger.debug(f"Bucket setup note: {e}")
pass
async def acreate_file(self, file_path: str, content: BinaryIO) -> bool:
@ -82,39 +101,14 @@ class MinioFileSystem(BaseFileSystem):
self, file_path: str, expiration: int = 3600, force_inline: bool = False
) -> Optional[str]:
try:
def _presign():
response_headers = None
if force_inline and file_path.endswith(".txt"):
response_headers = {
"response-content-type": "text/plain",
"response-content-disposition": "inline",
}
# Generate URL with the main client
url = self.client.presigned_get_object(
self.bucket_name,
file_path,
expires=timedelta(seconds=expiration),
response_headers=response_headers,
)
# If we have different public endpoint, replace it in the URL
if self.endpoint != self.public_endpoint:
# Simple string replacement since presigned URLs are just strings
# Replace the endpoint in the URL
url = url.replace(
f"://{self.endpoint}/", f"://{self.public_endpoint}/"
)
url = url.replace(
f"Host={self.endpoint}", f"Host={self.public_endpoint}"
)
return url
url = await asyncio.to_thread(_presign)
# For MinIO in local development, return unsigned URLs
# This avoids signature mismatch issues when endpoint differs
# MinIO must be configured to allow anonymous read access
protocol = "https" if self.secure else "http"
url = f"{protocol}://{self.public_endpoint}/{self.bucket_name}/{file_path}"
return url
except S3Error:
except Exception as e:
logger.error(f"Error generating MinIO URL: {e}")
return None
async def aget_file_metadata(self, file_path: str) -> Optional[Dict[str, Any]]:

View file

@ -59,7 +59,7 @@ services:
- app-network
api:
image: chewieee/dograh-api:v7
image: dograhai/dograh-api:v1
volumes:
- shared-tmp:/tmp
environment:
@ -122,7 +122,7 @@ services:
- app-network
arq-worker:
image: chewieee/dograh-api:v7
image: dograhai/dograh-api:v1
volumes:
- shared-tmp:/tmp
environment:
@ -149,16 +149,23 @@ services:
# Sentry
ENABLE_SETRY: "false"
SENTRY_DSN: ""
command: >
bash -c "
cd /app/api &&
python -m arq api.tasks.arq.WorkerSettings
"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
minio:
condition: service_healthy
networks:
- app-network
ui:
image: chewieee/dograh-ui:v10
image: dograhai/dograh-ui:v1
environment:
NEXT_PUBLIC_NODE_ENV: "local"
NEXT_PUBLIC_AUTH_PROVIDER: "local"