127 lines
4.2 KiB
Markdown
127 lines
4.2 KiB
Markdown
# ai-gateway
|
|
|
|
`ai-gateway` is an internal gRPC service that turns free-form text into home
|
|
assistant actions. It asks Ollama to produce a structured intent, resolves that
|
|
intent against known Home Assistant lights, and calls `ha-gateway` for any
|
|
approved action.
|
|
|
|
## Runtime Flow
|
|
|
|
1. The service loads `.env`, configures logging and telemetry, and starts gRPC
|
|
on `GRPC_PORT`.
|
|
2. `AIService.Query` receives prompt text and an optional model name.
|
|
3. The app refreshes or reads the light cache from `ha-gateway`.
|
|
4. Ollama receives a prompt containing the user text and known lights.
|
|
5. The app parses the model output as JSON intent data.
|
|
6. Supported intents are executed through `ha-gateway`; unsupported or invalid
|
|
responses return a plain explanation without taking action.
|
|
|
|
## gRPC API
|
|
|
|
Defined in [proto/ai/v1/ai.proto](https://gitea.nik4nao.com/nik/home-services/src/branch/main/proto/ai/v1/ai.proto).
|
|
|
|
- `AIService.Query`: sends text to the AI command flow
|
|
- `AIService.ListModels`: returns model names reported by Ollama
|
|
|
|
Supported action intents currently focus on lights:
|
|
|
|
- turn on a light
|
|
- turn off a light
|
|
- list known lights
|
|
- no-op / unknown intent
|
|
|
|
## Configuration
|
|
|
|
Environment variables:
|
|
|
|
| Variable | Default | Description |
|
|
| --- | --- | --- |
|
|
| `GRPC_PORT` | `50052` | gRPC listen port |
|
|
| `OLLAMA_URL` | `http://192.168.7.96:11434` | Ollama base URL |
|
|
| `OLLAMA_MODEL` | `llama3` | Default model for queries without an explicit model |
|
|
| `OLLAMA_TIMEOUT` | `120s` | HTTP timeout for Ollama calls |
|
|
| `HA_GATEWAY_ADDR` | `ha-gateway.home-services.svc.cluster.local:50051` | gRPC address for `ha-gateway` |
|
|
| `HA_GATEWAY_SERVER_NAME` | `ha-gateway.home-services.svc.cluster.local` | Expected server name for TLS |
|
|
| `TLS_DIR` | empty | Enables mTLS for the server and gateway client when set |
|
|
| `OTEL_ENDPOINT` | empty | OTLP gRPC collector endpoint; empty disables telemetry |
|
|
| `LOG_LEVEL` | `info` | `debug`, `info`, `warn`, or `error` |
|
|
| `LOG_FORMAT` | `json` | `json` or `text` |
|
|
| `LIGHT_CACHE_TTL` | `60s` | Light discovery cache lifetime |
|
|
|
|
Example env file: [.env.example](https://gitea.nik4nao.com/nik/home-services/src/branch/main/ai-gateway/.env.example)
|
|
|
|
When `TLS_DIR` is set, the directory must contain `tls.crt`, `tls.key`, and
|
|
`ca.crt`.
|
|
|
|
## Local Run
|
|
|
|
Start `ha-gateway` first, then run:
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
go run ./cmd/gateway
|
|
```
|
|
|
|
Run from `ai-gateway/` so `godotenv` loads `ai-gateway/.env`.
|
|
|
|
For local plaintext development:
|
|
|
|
```text
|
|
HA_GATEWAY_ADDR=localhost:50051
|
|
TLS_DIR=
|
|
```
|
|
|
|
## Smoke Checks
|
|
|
|
```bash
|
|
grpcurl -plaintext -d '{"text":"list the lights","source":"local"}' \
|
|
localhost:50052 ai.v1.AIService/Query
|
|
|
|
grpcurl -plaintext -d '{}' localhost:50052 ai.v1.AIService/ListModels
|
|
```
|
|
|
|
Reflection is only registered when `LOG_LEVEL=debug`; otherwise call by using
|
|
the compiled proto descriptors or generated clients.
|
|
|
|
## Test And Build
|
|
|
|
```bash
|
|
go test ./...
|
|
go build ./...
|
|
```
|
|
|
|
Build the container image from the workspace root:
|
|
|
|
```bash
|
|
docker build -f ai-gateway/Dockerfile -t ai-gateway:dev .
|
|
```
|
|
|
|
Optionally pass a build version:
|
|
|
|
```bash
|
|
docker build -f ai-gateway/Dockerfile --build-arg VERSION=$(git rev-parse --short HEAD) -t ai-gateway:dev .
|
|
```
|
|
|
|
## Package Map
|
|
|
|
```text
|
|
cmd/gateway/ # process entrypoint and wiring
|
|
internal/adapters/primary/grpc/ # AIService gRPC server
|
|
internal/adapters/secondary/ollama/ # Ollama HTTP client
|
|
internal/adapters/secondary/hagateway/ # ha-gateway gRPC client
|
|
internal/app/ # query orchestration and intent dispatch
|
|
internal/config/ # environment loading
|
|
internal/core/domain/ # prompt, intent, and cache types
|
|
internal/core/ports/driven/ # app-facing LLM and HA interfaces
|
|
internal/logger/ # slog setup
|
|
internal/telemetry/ # OpenTelemetry setup
|
|
```
|
|
|
|
## Limitations
|
|
|
|
- Intent parsing depends on the selected model returning valid JSON.
|
|
- Light actions are supported; broader Home Assistant domains are not wired yet.
|
|
- The light cache is per-process memory and refreshes by TTL.
|
|
- Keep this service internal or protect it with mTLS; it does not implement
|
|
separate app-layer authorization.
|