AI Q&A system: Python RAG (FastAPI + OpenAI embeddings) + .NET 10 Clean Architecture API + SQL Server logging + xUnit/pytest + Docker Compose + GitHub Actions CI.
Portfolio project showing how to integrate AI capabilities into a production-style .NET backend.
- Python Retrieval-Augmented Generation with OpenAI embeddings (keyword fallback).
- .NET 10 Web API structured with Clean Architecture.
- API key authentication, ProblemDetails, rate limiting, and health checks.
- HTTP orchestration with Polly-based resilience on the RAG client.
- SQL Server persistence for consultation audit logs.
- Unit/integration tests and CI coverage artifacts.
- One-command local stack via Docker Compose.
Mario Ramb - Systems Engineer with 18+ years in enterprise .NET development. This project demonstrates AI integration on top of a production-grade .NET backend.
dotnet-rag-api/
|-- rag-service/ # Python FastAPI RAG service
|-- DotnetRagApi/ # .NET 10 API + Clean Architecture layers + tests
|-- docker/ # SQL init scripts for Compose
|-- docs/ # Architecture diagram
|-- docker-compose.yml
`-- LICENSE
- Python, FastAPI, OpenAI SDK (embeddings + chat), python-dotenv, pytest
- .NET 10, ASP.NET Core Web API, Dapper
- SQL Server
- Docker Compose
- xUnit + coverlet, GitHub Actions
- Client sends a question to the .NET endpoint (
POST /api/ask) withX-Api-Key. - Application use case invokes the Python RAG service (
POST /rag/ask). - Python retrieves relevant context with embeddings (or keyword fallback) and calls an LLM.
- Response returns to .NET and the use case persists an audit row in SQL Server.
- Logs can be queried from
GET /api/logs(authenticated).
Prerequisites: Docker Desktop, an OpenAI API key.
copy .env.example .env
# edit .env and set OPENAI_API_KEY
docker compose up --buildThen open:
- Scalar:
http://localhost:5000/scalar/v1 - Health:
http://localhost:5000/health - Readiness:
http://localhost:5000/health/ready
Default API key (override with API_KEY in .env):
change-me-demo-api-key
Example request:
curl -X POST http://localhost:5000/api/ask \
-H "Content-Type: application/json" \
-H "X-Api-Key: change-me-demo-api-key" \
-d "{\"pregunta\":\"What is retrieval augmented generation?\",\"usuario\":\"demo\",\"rol\":\"user\",\"topN\":2}"- .NET SDK 10+
- Python 3.10+
- SQL Server LocalDB / SQL Server / Docker SQL
- OpenAI API key
From rag-service:
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
copy .env.example .envStart:
uvicorn app:app --host 127.0.0.1 --port 8000 --reloadRun:
DotnetRagApi/database/create-database.sql
Copy DotnetRagApi/DotnetRagApi.Api/appsettings.example.json to appsettings.json and set:
ConnectionStrings:DefaultConnectionSecurity:ApiKeyRagApi:BaseUrl
cd DotnetRagApi
dotnet run --project .\DotnetRagApi.Api\DotnetRagApi.Api.csproj| Method | Route | Auth | Description |
|---|---|---|---|
POST |
/api/ask |
X-Api-Key |
Ask a question through RAG |
GET |
/api/logs?top=50 |
X-Api-Key |
Latest audit logs (top clamped 1..100) |
GET |
/health |
No | Liveness |
GET |
/health/ready |
No | SQL + Python readiness |
.NET:
cd DotnetRagApi
dotnet test .\DotnetRagApi.slnxPython:
cd rag-service
pytest -q- Demonstrates practical AI integration instead of isolated toy logic.
- Applies Clean Architecture so business orchestration stays testable.
- Shows cross-language integration (Python + .NET) with resiliency and health checks.
- Includes authentication, Docker packaging, automated tests, and CI.
- Domain/DTO fields intentionally use Spanish naming (
pregunta,respuesta) to match the business vocabulary. - Retrieval defaults to OpenAI embeddings (
RAG_RETRIEVAL_MODE=embeddings) with keyword fallback. - For cloud hosting, the Compose services map cleanly to Azure Container Apps / App Service + Azure SQL.
MIT - see LICENSE.