This project is a Witcher III FAQ that couples Retrieval-Augmented Generation with a story-aware Petri Net. It uses OpenAI for language generation while the Petri state machine constrains context selection. Demo: http://ec2-13-229-70-95.ap-southeast-1.compute.amazonaws.com/
- W⁻(p,t) = tokens transition t consumes from place p.
- W⁺(p,t) = tokens t produces into place p.
- A transition t is enabled iff every input place p has the required tokens.
python -m venv .venv
# Windows
.\.venv\Scripts\activate
# macOS/Linux
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # adjust DATABASE_URL if needed
python -m src.app.seed_data
npm install
npm run build:ts
uvicorn src.app.api:app --reload --port 8000curl -X POST http://127.0.0.1:8000/ask \
-H "Content-Type: application/json" \
-d '{"question":"Who is the Bloody Baron and how does it relate to Ciri?"}'Response example:
{
"answer": "The Bloody Baron, also known as Philip Strenger, is a key character in [Family Matters]...",
"sources": [
{"id": 13, "title": "Can Ciri become a witcher or Empress?"},
{"id": 12, "title": "How do my choices influence Ciri’s fate?"},
{"id": 3, "title": "Crookback Bog confrontation outcomes"},
{"id": 11, "title": "Dijkstra coup: side with him or stop him?"},
{"id": 1, "title": "Family Matters: Botchling vs Lubberkin — which is better?"}
]
}- Build locally with
docker build -t witcher-petri .if you need to test the image before pushing. - All runtime configuration comes from environment variables (
DATABASE_URL,OPENAI_API_KEY,OPENAI_MODEL,EMBEDDING_MODEL). The app reads the process environment first and only falls back to.envduring development. - The container listens on port 8000.
docker run --rm -p 8000:8000 \
-e DATABASE_URL="mysql+pymysql://admin:***@database-petri-instance-1.cv4g2ew64mig.ap-southeast-1.rds.amazonaws.com:3306/witcher?ssl_ca=/certs/ap-southeast-1-bundle.pem" \
-e OPENAI_API_KEY="sk-..." \
-e OPENAI_MODEL=gpt-4o-mini \
-e EMBEDDING_MODEL=text-embedding-3-small \
-v $(pwd)/certs:/certs:ro \
witcher-petriPlace the regional RDS bundle in certs/ap-southeast-1-bundle.pem so the container can verify Aurora.
.github/workflows/docker-image.ymlbuilds the container on pushes tomainand publishes it to Amazon ECR.- Configure repository secrets before running the workflow:
AWS_REGION— deployment region (e.g.ap-southeast-1).AWS_ROLE_ARN— IAM role GitHub can assume (or store access keys instead).ECR_REPOSITORY— destination ECR repository name.
- Each merge to
mainships a new image tagged with the commit SHA. Capture that tag for ECS deployments (the task definition template expects it).
- Prerequisites
- Create the ECR repository and grant the GitHub workflow permission to push images.
- Provision VPC subnets/security groups that allow outbound MySQL (Aurora) and inbound HTTP/HTTPS from your ALB or internet.
- Store secrets (
DATABASE_URL,OPENAI_API_KEY) in AWS SSM Parameter Store or Secrets Manager.
- Register the task definition
- Update
infra/ecs-task-definition.jsonwith your account IDs, region, IAM roles, secret ARNs, and image tag. - Register it:
aws ecs register-task-definition \ --cli-input-json file://infra/ecs-task-definition.json
- Update
- Create or update the service
Use
aws ecs create-cluster --cluster-name witcher-petri || true aws ecs create-service \ --cluster witcher-petri \ --service-name witcher-api \ --task-definition witcher-petri \ --launch-type FARGATE \ --desired-count 1 \ --platform-version LATEST \ --network-configuration "awsvpcConfiguration={subnets=[subnet-abc,subnet-def],securityGroups=[sg-123],assignPublicIp=ENABLED}"
aws ecs update-service --force-new-deploymentto roll out a new image after each release. - Load balancing (optional)
- Attach the service to an Application Load Balancer target group listening on port 80/443.
- Align the target group health check with
/healthto match the container health probe.
- Secrets and env vars
OPENAI_MODELandEMBEDDING_MODELremain static environment variables in the task definition.DATABASE_URLandOPENAI_API_KEYare sourced from the referenced SSM/Secrets Manager entries, so no.envfile is required on the host.