Agent ArenaClickHouse Workshops

00 Cài đặt

Chuẩn bị môi trường của bạn — OpenRouter, ClickHouse và Langfuse được kết nối ngay từ đầu.

Kết quả

Một repo đã clone với virtualenv Python đã cài, một file .env đã điền credentials cho OpenRouter, ClickHouse Cloud và Langfuse Cloud, một database arena trong ClickHouse Cloud đã seed dữ liệu thương mại điện tử tổng hợp, và dashboard cục bộ đang chạy tại http://localhost:5174 — tab Leaderboard hiện còn trống, điều đó là bình thường cho đến Module 01.

Vì sao

Benchmark harnesseval/harness.py · cuộc thiServing APIserving/api.py · productionmột core · hai bên gọi dùng lại nóAgent coreagents/prompt · model client · SQL guardOpenRoutermột API → mọi họ modelClickHousedữ liệu nghiệp vụ · view v_* (chỉ đọc)Langfuseexperiments · results · scores · traces — nguồn sự thật của leaderboardhỏi một model → SQLSELECT · view v_*lưu mọi kết quả

Một agent core, được dùng lại bởi hai bên gọi (benchmark harness và serving API); nó hỏi một model qua OpenRouter và đọc dữ liệu qua các view v_* chỉ đọc của ClickHouse. Langfuse lưu từng kết quả benchmark và cung cấp dữ liệu cho leaderboard thông qua Public API của nó.

Agent Arena là một agent core NL→SQL (agents/) được dùng lại bởi hai bên gọi — benchmark harness (eval/harness.py) và serving API chạy thật (serving/api.py) — nên bản demo và bản benchmark dùng đúng cùng một đường code: cùng prompt template, cùng model client, cùng sandbox SQL chỉ đọc. Đó là điều làm cho các con số của benchmark trở thành dự báo đáng tin cho hành vi trên production, thay vì một "eval harness" riêng biệt âm thầm lệch khỏi những gì thực sự được đưa lên production.

Hãy để ý rằng Langfuse là một trong ba tài khoản bạn thiết lập ngay ở module đầu tiên này — trước khi bạn chọn model, trước khi bạn chạy dù chỉ một câu hỏi. Đó là chủ ý: Langfuse không phải thứ bạn gắn thêm vào sau khi chatbot đã chạy được, nó là công cụ chạy cuộc thi ở Mô-đun 01, đo chất lượng offline của người thắng ở Mô-đun 02, phát hiện điểm mù production ở Mô-đun 03, hỗ trợ điều tra của con người ở Mô-đun 04, rồi chứng minh và giám sát cải tiến ở Mô-đun 05 — một project, một chuỗi bằng chứng xuyên suốt. một đường code duy nhất đó và một project Langfuse duy nhất đó, nên làm đúng ba tài khoản và database đã seed ngay tại đây là điều khiến phần còn lại của workshop chạy trơn tru.

Khái niệm — bên dưới lớp vỏ

Ba trụ cột, ba nhiệm vụ, được nối với nhau ngay từ module đầu tiên này:

  • OpenRouter — một API tương thích OpenAI đứng trước mọi họ model trong workshop này (Anthropic, OpenAI, Google, DeepSeek, Qwen, Z.ai). Thay vì phải xoay xở với sáu SDK của sáu nhà cung cấp và sáu bộ credentials, agent core (agents/) dùng một client duy nhất để chạm tới cả sáu model trong config.yaml. Đó là điều làm cho một cuộc thi công bằng, so sánh tương đương ở Module 01 trở nên khả thi: mọi model chỉ cách nhau một chuỗi model=, sau cùng một endpoint, cùng một dạng request.
  • ClickHouse — database của ứng dụng. Nó chứa dữ liệu nghiệp vụ (các bảng thương mại điện tử tổng hợp bạn sắp seed) phía sau các view v_*. Agent chỉ luôn được phép SELECT từ các view v_* — không bao giờ từ bảng gốc, không bao giờ được ghi — vừa vì đó là một hợp đồng chỉ đọc ổn định, có tài liệu để agent suy luận trên đó, vừa vì agents/sqlguard.py cưỡng chế nó như một sandbox chỉ cho SELECT: nó phân tích SQL được sinh ra và từ chối bất cứ thứ gì không phải một câu lệnh SELECT/WITH…SELECT duy nhất, và chặn một danh sách đen các từ khóa ghi/DDL (INSERT, UPDATE, DELETE, DROP, ALTER, SYSTEM, …) kể cả khi chúng nằm bên trong một câu lệnh hợp lệ khác.
  • Langfuse — nơi lưu eval, leaderboard và observability. Nó được kết nối ngay lúc này, trước khi bạn chọn model hay hỏi dù chỉ một câu, bởi nó không phải thứ gắn thêm để dùng về sau — nó là công cụ chấm điểm cuộc thi ở Module 01, cho bạn đào sâu vào chất lượng ở Mô-đun 02, phát hiện lỗi production ở Mô-đun 03, lưu review của con người ở Mô-đun 04 và xác minh traffic tương lai ở Mô-đun 05. Một project, một chuỗi bằng chứng liên tục.

Ảnh chụp màn hình: trang Settings → API Keys của project Langfuse Cloud, cho thấy cặp public/secret key bạn dán vào .env đến từ đâu — hãy chụp từ UI thật.

Bẫy — OPENROUTER_API_KEY còn là placeholder. .env.example đi kèm OPENROUTER_API_KEY=sk-or-... như một mẫu, không phải key thật. Nếu bạn quên ghi đè nó, mọi lệnh gọi model ở Module 01 sẽ thất bại với lỗi xác thực của OpenRouter, không phải lỗi ClickHouse hay Langfuse — nên hãy kiểm tra .env trước nếu đó là lỗi bạn thấy.

Bẫy — sai host hoặc region của ClickHouse. CLICKHOUSE_CLOUD_HOST phải là đúng host trong phần connection details của service của bạn (theo region, ví dụ abc123.us-east-1.aws.clickhouse.cloud), không phải domain chung clickhouse.cloud. Host sai sẽ thất bại ngay với lỗi DNS/kết nối trong lúc scripts/arena.sh up — đó là dấu hiệu cần nhận ra.

Bẫy — ARENA_RO_PASSWORD không khớp. scripts/arena.sh up tạo user chỉ đọc arena_ro bằng đúng giá trị ARENA_RO_PASSWORD tại thời điểm đó. Nếu bạn đổi giá trị trong .env sau đó mà không chạy lại phần cài đặt (hoặc xóa và tạo lại user), kết nối chỉ đọc của agent sẽ bắt đầu xác thực thất bại dù .env "trông có vẻ đúng".

Mục tiêu

Ba bộ credentials trong .env, một database arena đã seed cùng các view v_* mà agent sẽ truy vấn, và dashboard cục bộ mở được trong trình duyệt.

Bước 1 — Tạo ba tài khoản

Bạn cần API credentials từ ba service trước khi chạm vào terminal:

ServiceBạn cần gìLấy ở đâuBiến trong .env
OpenRouterMột OPENROUTER_API_KEYopenrouter.ai → Keys. OpenRouter đứng trước mọi họ model dùng trong workshop này (Anthropic, OpenAI, Google, DeepSeek, Qwen, Z.ai) sau một API tương thích OpenAI.OPENROUTER_API_KEY, OPENROUTER_BASE_URL
Langfuse CloudPublic key + secret key của một projectcloud.langfuse.com → tạo một project → Settings → API Keys.LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_BASE_URL
ClickHouse CloudHost, admin user, admin passwordclickhouse.com/cloud → tạo một service → connection details.CLICKHOUSE_CLOUD_HOST, CLICKHOUSE_CLOUD_USER, CLICKHOUSE_CLOUD_PASSWORD

Giữ cả ba ở nơi dễ lấy — bạn sẽ dán chúng vào .env ngay sau đây.

Thiết lập privacy trên OpenRouter cần cho Qwen

Trong OpenRouter, mở Settings → Privacy → Data Policies → Zero Data Retention và tắt Non-frontier (toggle phải ở trạng thái xám/off). Qwen nằm trong nhóm model non-frontier của OpenRouter, và endpoint Alibaba khả dụng của nó không đủ điều kiện khi Zero Data Retention cho non-frontier đang được cưỡng chế. Nếu vẫn để bật, qwen/qwen3.7-flash sẽ thất bại với No endpoints available matching your guardrail restrictions and data policy dù API key và model slug đều hợp lệ.

Workshop này gửi các câu hỏi và schema thương mại điện tử tổng hợp. Với khối lượng công việc thật, hãy xem lại yêu cầu về quyền riêng tư của tổ chức bạn trước khi nới lỏng một chính sách ZDR.

Bước 2 — Clone repo

Agent Arena nằm trong monorepo ClickHouse_Demos, dưới workshops/agent_arena trên nhánh build-workshop-v1. Clone toàn bộ repo, rồi chuyển vào thư mục con đó — mọi lệnh từ đây trở đi đều giả định bạn đang đứng trong đó:

git clone --branch build-workshop-v1 --single-branch https://github.com/ClickHouse/ClickHouse_Demos.git
cd ClickHouse_Demos/workshops/agent_arena

Bước 3 — Tạo virtualenv và cài dependencies

python3.11 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt

Bước 4 — Cấu hình .env

Sao chép file mẫu:

cp .env.example .env

.env

Điền các giá trị từ Bước 1 — mọi giá trị dưới đây đều đang trống hoặc là placeholder trong .env.example:

# ClickHouse Cloud (business data queried by the agent)
export CLICKHOUSE_CLOUD_HOST=xxx.clickhouse.cloud
export CLICKHOUSE_CLOUD_USER=default
export CLICKHOUSE_CLOUD_PASSWORD=
export CLICKHOUSE_CLOUD_DATABASE=arena
export ARENA_RO_PASSWORD=
# OpenRouter (LLM provider)
export OPENROUTER_API_KEY=sk-or-...
export OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
# Langfuse Cloud (eval store + tracing)
export LANGFUSE_BASE_URL=https://us.cloud.langfuse.com
export LANGFUSE_PUBLIC_KEY=pk-lf-...
export LANGFUSE_SECRET_KEY=sk-lf-...

Từng khối dùng để làm gì:

  • CLICKHOUSE_CLOUD_* — credentials admin của service ClickHouse Cloud của bạn. Phần cài đặt dùng user admin đúng một lần, để tạo database arena và một user chỉ đọc riêng (arena_ro) mà agent sẽ truy vấn qua đó trong suốt phần còn lại của workshop.
  • ARENA_RO_PASSWORD — chọn bất kỳ mật khẩu nào; nó trở thành mật khẩu của arena_ro khi user chỉ đọc được tạo.
  • OPENROUTER_* — key OpenRouter của bạn và base URL của nó. Mọi model trong config.yaml đều được gọi qua đúng endpoint này.
  • LANGFUSE_* — host và các key của project Langfuse Cloud của bạn. Đây là nơi mọi trace, score và dataset trong workshop được lưu, từ lần chạy Arena đầu tiên ở Module 01 cho tới vòng lặp cải tiến được giám sát ở Mô-đun 05.

Bước 5 — Seed ClickHouse bằng dữ liệu thương mại điện tử tổng hợp

Bước này tạo database arena, user chỉ đọc arena_ro, sinh dữ liệu thương mại điện tử tổng hợp (customers, products, orders, order items, events) trực tiếp vào ClickHouse, và dựng các view v_* mà agent sẽ truy vấn:

source .env && scripts/arena.sh up

Mọi agent, mọi prompt và mọi đoạn SQL golden trong workshop này đều truy vấn các view v_customers, v_products, v_orders, v_order_items và v_events — không bao giờ truy vấn bảng gốc.

scripts/arena.sh up cũng khởi động dashboard API và web UI cục bộ. Khi nó chạy xong, mở http://localhost:5174 — tab Leaderboard sẽ trống cho đến khi bạn chạy cuộc thi ở Module 01.

Một lần chạy khỏe mạnh trông như thế nào. scripts/arena.sh up in ra, theo thứ tự:

  1. ClickHouse: business database + read-only agent user — database arena và user arena_ro riêng được tạo.
  2. Seeding ClickHouse directly + views + schema context — một dòng clickhouse: inserted <N> into <table> cho mỗi bảng (customers, products, orders, order_items, events), rồi done, rồi các view v_* và schema context mà agent đọc được dựng lên.
  3. Starting dashboard API (:8000) + web UI (:5174) — hai dòng [ready]. Nếu một trong hai báo [NOT up], khả năng cao port đã bị chiếm; hãy xem đường dẫn log nó in ra (.run/dashboard-api.log hoặc .run/web.log).

Output terminal cho thấy dashboard API của Agent Arena đã ready trên port 8000 và web UI đã ready trên port 5174

Dashboard Agent Arena ở lần tải đầu tiên với Leaderboard trống và chưa có dữ liệu lần chạy nào

Bạn có thể kiểm tra lại bất cứ điều nào ở trên về sau bằng scripts/arena.sh status, lệnh này in ra các server có đang chạy không và số dòng của từng view v_*.

Cách xác nhận bạn đã xong

  • .env có giá trị thật (không phải placeholder) cho CLICKHOUSE_CLOUD_*, OPENROUTER_* và LANGFUSE_*.
  • scripts/arena.sh up kết thúc không lỗi.
  • http://localhost:5174 mở được trong trình duyệt, hiển thị tab Leaderboard (trống là đúng ở thời điểm này).

Bài tập — làm hỏng và chẩn đoán một kết nối

Hãy tập nhận ra một giá trị .env bị sai qua dấu hiệu lỗi của nó, một cách có chủ ý, khi chưa có gì để mất:

  1. Mở .env và đổi một ký tự trong ARENA_RO_PASSWORD (hoặc tạm comment nó lại).
  2. Chạy lại source .env && scripts/arena.sh up. Nó vẫn nên đi qua được các bước dùng admin ClickHouse (những bước đó dùng credentials admin), nhưng hãy để ý xem đường chỉ đọc — bất cứ thứ gì kết nối bằng arena_ro — bắt đầu báo lỗi ở đâu.
  3. Đọc kỹ thông báo lỗi: đó là lỗi xác thực, lỗi "user does not exist", hay im lặng rồi timeout? Ghi lại bạn nhận được lỗi nào.
  4. Phục hồi ARENA_RO_PASSWORD đúng và chạy lại scripts/arena.sh up. Xác nhận nó hoàn tất sạch sẽ trở lại.

Đây chính là bản năng chẩn đoán bạn sẽ cần về sau khi phần cài đặt của một đồng nghiệp "không chạy" — đối chiếu nội dung lỗi với dịch vụ nào trong ba dịch vụ đang bị cấu hình sai, thay vì kiểm tra lại mọi thứ.

Tổng kết

Bạn đã có một database ClickHouse đã seed, credentials cho cả ba service — bao gồm Langfuse, được kết nối trước khi chọn bất kỳ model nào — và dashboard cục bộ đang chạy. Mọi thứ sau module này đều dùng lại đúng môi trường đó và đúng project Langfuse đó; không còn bước cài đặt nào nữa.

Trạng thái kết thúc

Môi trường đã sẵn sàng. Tiếp tục sang 01 Chọn model nền để chạy cuộc thi trên chính dữ liệu này.

Trên trang này

Track your progress?

Optional. We email a link to confirm your address; progress records once you open it.

Please use your work email address, not a personal one.

Progress tracking also requires accepting the current Terms of Service in Privacy settings.

VI