1What is this tool?
Imagine you have a quality inspector for your AI assistants. Whenever your AI gives an answer, this tool rates it: is it accurate? Is it relevant? Is it honest? That way you can improve your AI before showing it to your customers.
Quality scores
Every answer gets a score from 0 to 1 on faithfulness and relevancy.
Compare versions
Test two versions of your AI side by side and see which one wins.
Complete history
Every evaluation is logged so you can track progress over time.
100% private
Everything stays inside your company. Nothing goes online.
It is like a teacher for your AI. It grades every answer so you know which ones are good, which ones need improvement, and which version of your AI is better.
2How to enter the application
You only need a web browser and a URL provided by your administrator.
Open your browser
Chrome, Safari, Edge or Firefox. No installation needed.
Type the URL
Your administrator will give you two URLs: one for the Langfuse dashboard and one for the API documentation.
Langfuse UI: http://your-company.com:3000
API Docs: http://your-company.com:8000/docs
Sign in to Langfuse
The first time, create your admin account. After that, just log in with your email and password.
Ask your administrator to verify that ports 3000 and 8000 are open on the server.
3Key concepts (in plain language)
Before using the tool, here are the 3 concepts you need to understand. No technical knowledge required.
Faithfulness
Does the answer match the source material? If the AI invents things not in the source, faithfulness is low. Higher is better.
Relevancy
Does the answer actually respond to what was asked? If the AI talks about something else, relevancy is low. Higher is better.
Overall score
The average of faithfulness and relevancy. A simple number to compare answers quickly.
Score scale
| Score | Meaning |
|---|---|
| 0.9 - 1.0 | Excellent. The answer is accurate and relevant. |
| 0.7 - 0.9 | Good. Minor issues that could be improved. |
| 0.5 - 0.7 | Acceptable. Needs review before using with customers. |
| Below 0.5 | Poor. The answer has significant problems. |
4Evaluate an answer
This is the most common action. You provide the AI answer, the question, and the source context. The tool rates the answer.
What you need to provide
- Question: what the user asked the AI.
- Answer: what the AI responded.
- Context (optional): the source material the AI should have used. If provided, faithfulness is calculated against it.
- Agent name (optional): a label to track which AI agent was evaluated.
How to do it
Open the API documentation
Go to http://your-company.com:8000/docs in your browser.
Find the POST /evaluate endpoint
Click on it to expand, then click Try it out.
Fill the form
Enter the question, answer and optional context. Click Execute.
See the scores
The response shows faithfulness, relevancy and overall scores. Takes 30-60 seconds per evaluation.
The very first evaluation takes longer (up to 2 minutes) because the AI model loads into memory. Subsequent evaluations are faster.
5Compare two answers
If you are testing a new version of your AI, use this to see which version produces better answers.
When to use this
- You changed the AI model and want to know if it improved.
- You updated the AI prompt and want to compare results.
- Two different AI agents answer the same question and you need to pick one.
How to do it
Open the API documentation
Go to http://your-company.com:8000/docs
Find POST /compare
Click Try it out and enter the question, answer A, and answer B.
See the winner
The response shows both scores and declares a winner (A, B, or TIE).
Create a list of 10-20 test questions that cover your most important use cases. Run the same set against every version of your AI. This gives you a reliable benchmark.
6View results in the dashboard
All evaluations are stored in Langfuse. You can browse them, filter by agent, and track quality over time.
What you will see
- Traces: every evaluation with its input, output and scores.
- Sessions: groups of related traces (for example, all evaluations of one agent).
- Scores: the numeric quality scores you can filter and chart.
- Dashboard: aggregate charts showing quality trends over time.
Instead of guessing whether your AI is good, you have numbers. When your team asks should we ship this new version?, you can answer with data.
7Common issues
| Issue | Solution |
|---|---|
| The evaluation takes too long | Wait 30-60 seconds. The first one takes longer because the AI model loads into memory. |
| The dashboard does not load | Verify port 3000 is open in the Security Group. Contact your administrator if unsure. |
| Score is 0.0 in both metrics | The AI judge model might not be loaded yet. Try again in 30 seconds. |
| The answer seems wrong | Verify the context is complete. The judge evaluates faithfulness against the context you provide. |
| Cannot access Langfuse UI | Contact your administrator to verify the service is running and the port is open. |
8Best practices
To get meaningful results
- Always provide context: faithfulness without context is meaningless. Include the source text the AI should have used.
- Test with real questions: use the same questions your customers would ask.
- Compare systematically: run the same set of test cases against every version of your AI.
- Track over time: scores should improve with each iteration. If they drop, you introduced a regression.
- Combine with human review: metrics are helpful but not perfect. Spot-check important answers manually.
What to avoid
- Do not judge answers without providing context; the score will be unreliable.
- Do not trust a single evaluation; run several to see consistency.
- Do not share evaluation data with customers; it is internal quality data.
You are ready!
Start evaluating your AI agents with data instead of intuition.
1Full stack architecture
Complete DevOps stack for AI agents deployed on a single EC2 g4dn instance with GPU acceleration.
| Layer | Technology | Port |
|---|---|---|
| Operating System | Ubuntu 26.04 LTS - kernel 7.0 AWS | - |
| GPU Runtime | NVIDIA Driver 580 - CUDA 13 | - |
| LLM Judge | Ollama - llama3.1:8b (judge model) | 11434 |
| Observability | Langfuse v2 (self-hosted) | 3000 |
| Metadata DB | PostgreSQL 16 | 5432 (localhost) |
| Cache and Queues | Redis 7 | 6379 (localhost) |
| REST API | FastAPI + Uvicorn (systemd) | 8000 |
Important system paths
# DevOps runtime
/opt/devops-server/
app/ # FastAPI code
main.py
config.py
routers/ # health, evaluate, compare, traces
utils/ # ollama_judge, langfuse_client
venv/ # Python 3.12 with deps
logs/ # api.log, api-error.log
docker-compose.yml # Langfuse + PostgreSQL + Redis
systemd services
devops-api.service -> uvicorn app.main:app on :8000
docker.service -> manages Langfuse, PostgreSQL, Redis containers
ollama.service -> LLM judge runtime on :11434
2API endpoints
REST API documented with OpenAPI. Swagger UI available at /docs.
| Method | Endpoint | Description |
|---|---|---|
| GET | / | Service info |
| GET | /health | Healthcheck with Langfuse and Ollama status |
| POST | /evaluate | Evaluate a single answer (faithfulness + relevancy) |
| POST | /compare | Compare two answers and declare a winner |
| POST | /traces | Create a trace in Langfuse |
| GET | /docs | Swagger UI |
Request schemas
# POST /evaluate
{
"question": "string",
"answer": "string",
"context": "string (optional)",
"agent_name": "string (optional)",
"trace_id": "string (optional)"
}
# POST /compare
{
"question": "string",
"answer_a": "string",
"answer_b": "string",
"context": "string (optional)"
}
# POST /traces
{
"name": "string",
"input": "string",
"output": "string",
"metadata": {"key": "value"}
}
3curl examples
Healthcheck
curl -s http://localhost:8000/health | jq
Evaluate an answer
curl -X POST http://localhost:8000/evaluate \
-H "Content-Type: application/json" \
-d '{
"question": "What is the capital of France?",
"answer": "The capital of France is Paris.",
"context": "France is a country in Europe. Its capital city is Paris.",
"agent_name": "geography-agent"
}' | jq
Compare two versions
curl -X POST http://localhost:8000/compare \
-H "Content-Type: application/json" \
-d '{
"question": "What is recursion?",
"answer_a": "Recursion is when a function calls itself.",
"answer_b": "Recursion is a programming technique where a function calls itself to solve smaller instances of the same problem.",
"context": "Recursion is a fundamental concept in computer science."
}' | jq
Create a trace
curl -X POST http://localhost:8000/traces \
-H "Content-Type: application/json" \
-d '{
"name": "test-trace",
"input": "What is Python?",
"output": "Python is a high-level programming language.",
"metadata": {"agent": "test", "version": "1.0"}
}' | jq
Evaluation: 30-60 seconds per answer (2 LLM calls). Compare: 60-120 seconds (4 LLM calls). First call is slower because the model loads into GPU memory.
4Evaluation metrics
How LLM-as-Judge works
- You submit a question, an answer, and optional context
- The API sends a structured prompt to the judge LLM (llama3.1:8b)
- The LLM returns a numeric score from 0 to 1
- The API parses the score and returns it as JSON
Available metrics
| Metric | Question it answers | Range |
|---|---|---|
faithfulness | Is the answer factually consistent with the context? | 0.0 - 1.0 |
answer_relevancy | Does the answer address the question asked? | 0.0 - 1.0 |
overall_score | Average of the two above. | 0.0 - 1.0 |
Change the judge model
Edit /opt/devops-server/app/config.py:
judge_model: str = "llama3.1:8b"
Recommended alternatives:
llama3.2:3b- faster, lower qualityqwen2.5:14b- slower, higher qualitymistral:7b- balanced option
After change: sudo systemctl restart devops-api
5Langfuse observability
What is Langfuse
Langfuse is an open-source observability platform for LLM applications. It stores traces (inputs, outputs, scores) and provides a UI to browse, filter and chart them.
Access
http://<IP>:3000
Initial setup (first time only)
- Open Langfuse UI
- Create admin account (email + password)
- Create organization and project
- Go to Settings - API Keys - Create new API key
- Copy Public Key and Secret Key
Configure API keys
sudo -u ubuntu tee -a /opt/devops-server/.env > /dev/null <<'EOF'
LANGFUSE_PUBLIC_KEY=pk-lf-xxxxxxxxxxxxxxxx
LANGFUSE_SECRET_KEY=sk-lf-xxxxxxxxxxxxxxxx
EOF
sudo systemctl restart devops-api
Container architecture
devops-langfuse-server Langfuse UI and API :3000
devops-postgres Metadata storage :5432 (internal)
devops-redis Cache and queues :6379 (internal)
6systemd services
Basic commands
# Status
sudo systemctl status devops-api docker ollama
# Restart the API
sudo systemctl restart devops-api
# Restart Docker containers
sudo docker restart devops-langfuse-server devops-postgres devops-redis
# Check if enabled at boot
sudo systemctl is-enabled devops-api docker ollama
devops-api service structure
# /etc/systemd/system/devops-api.service
[Unit]
Description=AI Agent DevOps Server API
After=network.target docker.service
Wants=docker.service
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/opt/devops-server
Environment="PATH=/opt/devops-server/venv/bin:/usr/local/bin:/usr/bin:/bin"
ExecStart=/opt/devops-server/venv/bin/uvicorn \
app.main:app --host 0.0.0.0 --port 8000 --workers 1
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
7Logs and monitoring
API logs
sudo journalctl -u devops-api -f
sudo journalctl -u devops-api -n 100 --no-pager
tail -f /opt/devops-server/logs/api.log
tail -f /opt/devops-server/logs/api-error.log
Container logs
sudo docker logs -f devops-langfuse-server
sudo docker logs -f devops-postgres
sudo docker logs -f devops-redis
sudo docker stats
GPU monitoring
nvidia-smi
watch -n 2 nvidia-smi
nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv
Ports
sudo ss -tulpn | grep -E ':(3000|5432|6379|8000|11434)'
8Troubleshooting
| Symptom | Cause | Solution |
|---|---|---|
Connection refused :8000 |
API service down | sudo systemctl restart devops-api |
| 500 Internal Server Error on /evaluate | Missing judge model in Ollama | ollama pull llama3.1:8b |
| Score always 0.0 | Judge returns non-numeric output | Verify prompt in ollama_judge.py |
| Langfuse UI not loading | Container crashed | sudo docker restart devops-langfuse-server |
| PostgreSQL connection error | DB container unhealthy | sudo docker restart devops-postgres |
| Evaluate takes more than 3 minutes | Model loading on first request | Wait, subsequent requests are faster |
Quick diagnostic
# Services
systemctl is-active devops-api docker ollama
# Ports
sudo ss -tulpn | grep -E ':(3000|5432|6379|8000|11434)'
# API health
curl -s http://localhost:8000/health | jq
# Ollama models
ollama list
# Docker containers
sudo docker ps
# GPU
nvidia-smi
9Backup and restore
What to back up
/opt/devops-server/app/- your customized code/opt/devops-server/.env- configuration including Langfuse keys- PostgreSQL volume
devops-server_postgres-data- all traces and scores - Redis volume
devops-server_redis-data- cache and queues
Full backup
sudo tar -czf /tmp/devops-backup-$(date +%Y%m%d).tar.gz \
/opt/devops-server/app \
/opt/devops-server/.env
sudo docker run --rm \
-v devops-server_postgres-data:/data \
-v /tmp:/backup \
alpine tar czf /backup/devops-postgres.tar.gz -C /data .
scp ubuntu@your-ip:/tmp/devops-backup-*.tar.gz ./
Restore
sudo tar -xzf devops-backup-YYYYMMDD.tar.gz -C /
sudo systemctl restart devops-api
sudo docker restart devops-langfuse-server devops-postgres
Automate daily backups of the PostgreSQL volume with a cron job. Traces grow with every evaluation and are the core value of the product.