A hands-on AI engineering sandbox for learning multimodal routing, provider abstraction, and safe backend architecture.
kinder_Garden AI is a community-driven learning hub for developers who want to understand how AI systems are wired in the real world.
Modern AI apps rarely depend on one provider forever. A useful application may start with Gemini, add Groq for fast inference, use Ollama for local experiments, and later introduce image or audio workflows. Without a routing layer, every model swap leaks into the rest of the application.
This project teaches a cleaner pattern:
Keep application logic stable while model providers change underneath.
The backend exposes a consistent FastAPI interface, routes requests by mode/model, delegates work to provider-specific services, and returns a predictable JSON response.
| Status | Capability | Notes |
|---|---|---|
[PRODUCTION-READY] |
Text-to-Text endpoint | POST /api/chat accepts mode, query, model_name, and output_format. |
[PRODUCTION-READY] |
Provider registry | Models are declared in backend/config/model.yaml. |
[PRODUCTION-READY] |
Dynamic model routing | cloud_service.py resolves Google, Groq, Hugging Face, and Ollama providers. |
[PRODUCTION-READY] |
Safe temp-file cleanup | Upload paths use try...finally to remove temporary files. |
[EXPERIMENTAL] |
Image upload path | Image files are validated and staged for Image -> Text processing. |
[EXPERIMENTAL] |
Audio upload path | Audio files are validated and staged for Speech -> Text processing. |
[EXPERIMENTAL] |
Browser voice capture | Frontend can record microphone audio and submit it as a file. |
[PLANNED] |
Streaming tokens | Useful for long LLM responses. |
[PLANNED] |
Text-to-speech playback | Backend service exists; frontend playback is next. |
Built pieces:
[✓]FastAPI backend router inbackend/api/chat.py[✓]Text workflow inbackend/services/text_service.py[✓]Vision helper inbackend/services/image_service.py[✓]Speech helper inbackend/services/speech_service.py[✓]Provider abstraction inbackend/utils/cloud_service.py[✓]Next.js frontend shell with mode/model selectors[✓]Centralized logging for failed text model calls
| Tool | Required | Purpose |
|---|---|---|
| Python 3.13+ | Yes | FastAPI backend runtime |
| Node.js 20+ | Yes | Next.js frontend runtime |
| Google API key | Optional | Gemini text/vision models |
| Groq API key | Optional | Groq LLMs and Whisper transcription |
| Hugging Face key | Optional | Image generation / hosted endpoints |
| Ollama | Optional | Local or cloud-hosted Ollama models |
git clone <your-repo-url>
cd O_Genratorpython -m venv .venvWindows PowerShell:
.\.venv\Scripts\Activate.ps1macOS/Linux:
source .venv/bin/activateIf your branch has requirements.txt:
pip install -r requirements.txtThis repository also supports the current pyproject.toml / uv.lock workflow:
uv syncCreate a .env file in the project root:
GOOGLE_API_KEY=your_google_api_key_here
GROQ_API_KEY=your_groq_api_key_here
HUGGINGFACE_API_KEY=your_huggingface_api_key_hereUse only the keys required by the models you are testing.
uvicorn main:app --reloadBackend:
http://127.0.0.1:8000
API docs:
http://127.0.0.1:8000/docs
cd frontend
npm install
npm run devWindows PowerShell may require:
npm.cmd run devFrontend:
http://127.0.0.1:3000
| Runtime | Tag | How It Works | Common Failure |
|---|---|---|---|
| Ollama Local | [LOCAL-ONLY] |
Backend calls a local Ollama server at localhost:11434. |
WinError 10061 means Ollama is not running. |
| Ollama Cloud | [EXPERIMENTAL] |
Use a cloud-hosted Ollama-compatible endpoint if configured. | Provider URL/auth must be configured correctly. |
| Google Gemini | [CLOUD] |
Uses GOOGLE_API_KEY. |
Missing or invalid Google API key. |
| Groq | [CLOUD] |
Uses GROQ_API_KEY. |
Wrong model id or invalid Groq key. |
| Hugging Face | [CLOUD] |
Uses HUGGINGFACE_API_KEY. |
Missing token or unavailable model. |
Start Ollama locally:
ollama servePull a model:
ollama pull llavaCheck installed models:
ollama listSafety rule: If you select an Ollama model in the frontend, make sure the Ollama runtime is actually running before sending the request.
UI Clients
|
v
FastAPI Router
|
v
Strategy Dispatcher Switch
|
+--> Google GenAI
|
+--> Groq API
|
+--> Ollama Local
|
+--> Ollama Cloud
|
v
Unified JSON Response
The frontend sends multipart/form-data to:
POST /api/chat
| Field | Type | Example | Required |
|---|---|---|---|
mode |
string | text, image, audio |
Yes |
model_name |
string | gemini-2.5-flash, qwen/qwen3-32b, llava |
Yes |
query |
string | Explain transformers simply |
Required for text |
file |
file | image/audio upload | Required for image/audio |
output_format |
string | text, audio |
No |
{
"status": "success",
"mode": "text",
"response": "The model output appears here.",
"output_format": "text"
}Audio or image workflows may add:
{
"audio_file": "audio_outputs/example.wav",
"image_file": "backend/image_outputs/example.png"
}The first learning version uses a simple conditional dispatcher:
if mode == "text":
return process_text(...)
if mode == "image":
file_path = await save_upload_file(file)
return process_image(...)
if mode == "audio":
file_path = await save_upload_file(file)
return process_audio(...)| Pattern | Status | Why It Is Used |
|---|---|---|
| Simple Conditional Dispatcher | [PRODUCTION-READY] |
Easy to read, debug, and teach. |
| Provider Registry | [PRODUCTION-READY] |
Keeps model/provider mapping outside application logic. |
| Strategy Registry | [PLANNED] |
Future upgrade for more modes and fewer conditionals. |
Architecture rule: The frontend should not know how to call Gemini, Groq, or Ollama directly. It should only send
mode,model_name,query, and optionalfileto the backend.
Uploads are saved to:
tempfile.gettempdir() / "multimodal_uploads"
The backend cleans temporary files with try...finally:
try:
file_path = await save_upload_file(file)
result = process_image(file_path, query, model_name)
return build_response("image", result)
finally:
cleanup_temp_file(file_path)Safety rule: Every workflow that writes an upload to disk must clean it up in
finally, even when the AI provider fails.
This prevents large image/audio uploads from silently filling the host machine with dead files.
| Provider | Text | Vision | Audio | Local Runtime | Notes |
|---|---|---|---|---|---|
| Google Gemini | [✓] |
[✓] |
[•] |
No | Strong cloud text and vision support. |
| Groq | [✓] |
[•] |
[✓] |
No | Fast hosted inference and Whisper transcription. |
| Ollama Local | [✓] |
[✓] |
[•] |
Yes | Requires ollama serve. |
| Ollama Cloud | [px] |
[px] |
[•] |
No | Planned/experimental depending on endpoint setup. |
| Hugging Face | [px] |
[•] |
[px] |
No | Used for hosted endpoints and generation experiments. |
Legend:
[✓]implemented or structurally supported[px]experimental / provider-dependent[•]planned or not the current focus
Models live in:
backend/config/model.yaml
Example:
text:
models:
gemini-2.5-flash:
provider: google
qwen/qwen3-32b:
provider: groq
vision:
models:
gemini-2.5-pro:
provider: googleThe frontend must send the exact YAML key:
{ value: "qwen/qwen3-32b", label: "Text | Groq | qwen/qwen3-32b" }Routing rule: The
labelis cosmetic. Thevalueis the real model id sent to FastAPI.
O_Genrator/
main.py
backend/
api/
chat.py
config/
model.yaml
services/
text_service.py
image_service.py
speech_service.py
utils/
cloud_service.py
frontend/
app/
components/
app-shell/
| File | Responsibility |
|---|---|
main.py |
Creates the FastAPI app and mounts routers. |
backend/api/chat.py |
Main /api/chat dispatcher. |
backend/config/model.yaml |
Model/provider registry. |
backend/utils/cloud_service.py |
Creates provider clients. |
backend/services/text_service.py |
Text model workflow. |
backend/services/image_service.py |
Vision and image generation helpers. |
backend/services/speech_service.py |
Speech-to-text and text-to-speech helpers. |
frontend/components/app-shell/Chat.tsx |
Sends chat FormData to backend. |
frontend/components/app-shell/Sidebar.tsx |
Mode/model selection. |
Open AI Orchestrator is built to welcome both beginners and experienced AI engineers.
- Improve missing API key messages.
- Add request examples for
POST /api/chat. - Document known-good model ids for Gemini, Groq, and Ollama.
- Add UI warnings for local Ollama models.
- Add tests for text request validation.
- Connect Image -> Text through
process_image. - Connect Speech -> Text through
process_audio. - Add Text -> Speech playback in the frontend.
- Filter model dropdown by selected mode.
- Add structured loading and error states.
- Add streaming token responses.
- Replace conditionals with a strategy registry.
- Add provider fallback chains.
- Add structured logs with request IDs.
- Add persistent generated file storage.
- Add Docker Compose for backend, frontend, and Ollama.
| Step | Requirement |
|---|---|
| 1 | Fork the repository. |
| 2 | Create a focused feature branch. |
| 3 | Make one clear change. |
| 4 | Run local checks. |
| 5 | Open a PR explaining what changed, why it matters, and how it was tested. |
git checkout -b feature/your-feature-nameContribution rule: Small, well-tested improvements are valuable. A better error message can help the next learner move faster.
MIT. Update the repository with a LICENSE file before public release.
Open AI Orchestrator is an invitation to learn AI engineering by building the routing layer yourself. If you want to understand how text, vision, and audio workflows can share one backend without becoming tangled, this repo gives you a practical place to experiment.