Introduces a comprehensive, multi-tiered memory system to provide conversation history and context for the AI agent. This lays the foundation for more stateful and intelligent interactions. Key components of this implementation: - **Multi-Tiered Memory Architecture:** - **Tier 1 (Working Memory):** A fast, in-memory buffer (`ConversationBufferMemory`) that holds the most recent turns of a conversation for immediate access. - **Tier 3 (Long-Term Memory):** A persistent, semantic search-based memory store using Qdrant (`QdrantConversationMemory`). It stores all conversation turns as vector embeddings, enabling long-term recall and similarity search. - **Qdrant Integration:** - The `qdrant-client` is added to manage collections and perform vector search operations. - Each user is assigned a dedicated Qdrant collection for multi-tenancy. - **Ollama Embedding Client:** - A new `OllamaEmbeddingClient` generates text embeddings via the Ollama API, replacing the need for local sentence-transformer models. This significantly reduces the service's dependency footprint. - **Configuration and Stack Updates:** - The `config.py` and `core-ai.yml` stack file are updated with new settings for enabling memory, configuring Qdrant, and specifying the embedding model. - **Utility and Schema Additions:** - New Pydantic schemas (`memory/schemas.py`) define the data structures for conversation turns and memory management. - Utility functions (`utils.py`) are added for user ID sanitization and collection naming. This feature enhances the agent's capabilities by allowing it to maintain context across multiple turns and sessions, leading to more coherent and relevant responses.
Core-AI Service
Simplified AI service for testing LiteLLM → Ollama → Model integration without ADK complexity.
Purpose
This service strips away the ADK layer to isolate and debug the fundamental LiteLLM/Ollama integration. It provides:
- Direct LiteLLM integration - No ADK overhead
- OpenAI-compatible API - Drop-in replacement for testing
- Comprehensive diagnostics - Layered testing to identify issues
- Minimal complexity - Easy to understand and debug
Architecture
HTTP Request → SimpleLiteLLMAgent → LiteLLM → Ollama → Model → Response
Bypassed: Google ADK, tool calling, complex orchestration
Quick Start
1. Install Dependencies
pip install -r requirements.txt
2. Configure Environment
Create .env file or set environment variables:
OLLAMA_BASE_URL=http://ollama:11434
AGENT_MODEL=gemma2:9b-instruct-q5_K_M
SYSTEM_PROMPT_VARIANT=minimal_agent
HOST=0.0.0.0
PORT=8086
3. Run Diagnostics
# Check Ollama connectivity
python diagnostics/check_ollama.py
# Test direct LiteLLM
python diagnostics/test_litellm_direct.py
# Run full test suite
bash tests/run_all_tests.sh
4. Start Service
python main.py
Service will be available at http://localhost:8086
5. Test It
curl -X POST http://localhost:8086/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"messages": [
{"role": "user", "content": "What is the capital of France?"}
]
}'
API Endpoints
GET /health
Health check endpoint
Response:
{
"status": "ok",
"service": "core-ai"
}
POST /v1/chat/completions
OpenAI-compatible chat completions endpoint
Request:
{
"model": "test",
"messages": [
{"role": "user", "content": "Your question here"}
],
"stream": false
}
Response (non-streaming):
{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1234567890,
"model": "test",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "Response here"
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0
}
}
Streaming: Set "stream": true for Server-Sent Events response
Project Structure
services/core-ai/
├── main.py # HTTP server (aiohttp)
├── src/
│ ├── agent.py # SimpleLiteLLMAgent
│ ├── config.py # Configuration (Pydantic)
│ ├── prompts.py # System prompts
│ └── tools.py # (Unused in this version)
├── diagnostics/
│ ├── check_ollama.py # Ollama connectivity check
│ └── test_litellm_direct.py # Direct LiteLLM test
├── tests/
│ ├── test_01_environment.py # Config tests
│ ├── test_02_litellm_raw.py # Raw LiteLLM tests
│ ├── test_03_message_format.py # Message formatting
│ ├── test_04_agent.py # Agent logic tests
│ ├── test_05_api.py # API endpoint tests
│ ├── run_all_tests.sh # Run all tests
│ └── README.md # Test documentation
├── requirements.txt
├── Dockerfile
└── README.md (this file)
Configuration
Configuration is managed via src/config.py using Pydantic Settings.
Environment Variables
| Variable | Default | Description |
|---|---|---|
HOST |
0.0.0.0 |
Server host |
PORT |
8086 |
Server port |
OLLAMA_BASE_URL |
http://ollama:11434 |
Ollama API URL |
AGENT_MODEL |
gemma2:9b-instruct-q5_K_M |
Model name |
SYSTEM_PROMPT_VARIANT |
minimal_agent |
Prompt variant to use |
DEBUG |
false |
Enable debug mode |
LOG_LEVEL |
INFO |
Logging level |
Testing
See tests/README.md for comprehensive testing documentation.
Quick test:
bash tests/run_all_tests.sh
This runs 5 layers of tests to isolate issues:
- Environment & Configuration
- Raw LiteLLM Connection
- Message Formatting
- Agent Logic
- API Integration
Docker Deployment
Build
docker build -t core-ai:latest .
Run
docker run -d \
--name core-ai \
-p 8086:8086 \
-e OLLAMA_BASE_URL=http://ollama:11434 \
-e AGENT_MODEL=gemma2:9b-instruct-q5_K_M \
--network docker-dataplane \
core-ai:latest
Using Docker Compose
docker-compose -f ../../stacks/core-ai.yml up
Troubleshooting
Service won't start
- Check logs:
docker logs core-ai - Verify Ollama is running:
docker ps | grep ollama - Run diagnostics:
python diagnostics/check_ollama.py
No response or timeout
- Check Ollama logs:
docker logs ollama - Model may be loading (first run takes 30-60s)
- Verify model exists:
docker exec ollama ollama list - Test directly:
docker exec ollama ollama run gemma2:9b-instruct-q5_K_M "test"
Wrong or empty responses
- Check system prompt is loaded (see agent logs)
- Verify prompt variant exists in
src/prompts.py - Run Layer 3 tests:
pytest tests/test_03_message_format.py -v
Connection refused
- Check network:
docker network inspect docker-dataplane - Verify both services are on the same network
- Try using container IP instead of hostname
Development
Adding New Prompts
Edit src/prompts.py:
PROMPTS = {
"minimal_agent": "You are a helpful assistant.",
"my_new_prompt": "Your custom system prompt here."
}
Update environment variable:
SYSTEM_PROMPT_VARIANT=my_new_prompt
Modifying Agent Behavior
Edit src/agent.py - specifically the SimpleLiteLLMAgent class.
Key methods:
__init__()- Initialization and configurationchat()- Streaming chat handlerchat_completion()- Non-streaming completion handler
Adding Tests
Add to appropriate test layer in tests/:
- Configuration changes →
test_01_environment.py - LiteLLM behavior →
test_02_litellm_raw.py - Message formatting →
test_03_message_format.py - Agent logic →
test_04_agent.py - API changes →
test_05_api.py
Comparison with Core-API
| Feature | Core-AI | Core-API |
|---|---|---|
| ADK Integration | ❌ No | ✅ Yes |
| Tool Calling | ❌ No | ✅ Yes |
| System Orchestration | ❌ No | ✅ Yes |
| Complexity | Low | High |
| Purpose | Debugging | Production |
| Direct LiteLLM | ✅ Yes | ❌ No |
| Diagnostics | ✅ Comprehensive | Limited |
Next Steps
If Tests Pass
- ✅ Foundation is solid
- Consider migrating fixes to core-api
- Add ADK layer back in phases
- Test tool calling integration
If Tests Fail
- Run diagnostics to identify layer
- Fix that specific layer
- Re-run tests
- Proceed once all pass
Contributing
When making changes:
- Run diagnostics first
- Make changes
- Run full test suite
- Update relevant documentation
- Test in Docker environment
License
Part of the tower-of-joy project.