Agent ArenaClickHouse Workshops

00 ตั้งค่า

เตรียมสภาพแวดล้อมของคุณให้พร้อม — เชื่อมต่อ OpenRouter, ClickHouse และ Langfuse ตั้งแต่เริ่ม

ผลลัพธ์

repo ที่ clone แล้วพร้อม Python virtualenv ที่ติดตั้งเรียบร้อย, .env ที่กรอก credential ของ OpenRouter, ClickHouse Cloud และ Langfuse Cloud, ฐานข้อมูล arena ใน ClickHouse Cloud ที่ seed ข้อมูล e-commerce สังเคราะห์แล้ว และ dashboard ในเครื่องที่รันอยู่ที่ http://localhost:5174 — แท็บ Leaderboard ยังว่างอยู่ตอนนี้ ซึ่งเป็นเรื่องปกติจนกว่าจะถึง โมดูล 01

ทำไม

Benchmark harnesseval/harness.py · the contestServing APIserving/api.py · productionone core · two callers reuse itAgent coreagents/prompt · model client · SQL guardOpenRouterone API → all model familiesClickHousebusiness data · v_* views (read-only)Langfuseexperiments · results · scores · traces — the leaderboard source of truthask a model → SQLSELECT · v_* viewsstore every result

agent core หนึ่งชุด ใช้ซ้ำโดยผู้เรียกสองราย (benchmark harness และ serving API); มันถามโมเดล ผ่าน OpenRouter และอ่านข้อมูลผ่าน view v_* แบบอ่านอย่างเดียวของ ClickHouse Langfuse เก็บผลลัพธ์ benchmark ทุกรายการและขับเคลื่อน leaderboard ผ่าน Public API ของมัน

Agent Arena คือ agent core สำหรับ NL→SQL หนึ่งชุด (agents/) ที่ถูกใช้ซ้ำโดยผู้เรียกสองราย — benchmark harness (eval/harness.py) และ serving API ที่ทำงานจริง (serving/api.py) — ทำให้เดโม และ benchmark ใช้เส้นทางโค้ดเดียวกันเป๊ะ ๆ: prompt template เดียวกัน, model client เดียวกัน, SQL sandbox แบบอ่านอย่างเดียวเดียวกัน นั่นคือสิ่งที่ทำให้ตัวเลขจาก benchmark เป็น ตัวทำนายพฤติกรรมบน production ที่เชื่อถือได้ ต่างจาก "eval harness" แยกอีกชุด ที่แอบเบี่ยงออกจากสิ่งที่ปล่อยจริง

สังเกตว่า Langfuse เป็นหนึ่งในสามบัญชีที่คุณตั้งค่าในโมดูลแรกสุดนี้ — ก่อนที่คุณจะเลือกโมเดล ก่อนที่คุณจะรันคำถามแม้แต่ข้อเดียว นั่นเป็นเรื่องตั้งใจ: Langfuse ไม่ใช่สิ่งที่คุณมาแปะเพิ่มเมื่อ chatbot ทำงานได้แล้ว มันคือเครื่องมือที่ คุม การแข่งขันในโมดูล 01 วัดคุณภาพของผู้ชนะในโมดูล 02 ขับเคลื่อนวงจร พัฒนาในโมดูล 03 และเฝ้าดู production ในโมดูล 04 — โปรเจกต์เดียว ชุด traces และ datasets ชุดเดียว ตั้งแต่ต้นจนจบ ทุกโมดูลหลังจากนี้ต่อยอดจาก เส้นทางโค้ดเดียวนั้นและโปรเจกต์ Langfuse เดียวนั้น ดังนั้นการทำสามบัญชีและฐานข้อมูล ที่ seed แล้วให้ถูกต้องตรงนี้คือสิ่งที่ทำให้ส่วนที่เหลือของเวิร์กช็อปทำงานได้เลย

แนวคิด — เบื้องหลังการทำงาน

สามเสาหลัก สามหน้าที่ ต่อเข้าด้วยกันตั้งแต่โมดูลแรกนี้:

  • OpenRouter — API หนึ่งตัวที่เข้ากันได้กับ OpenAI วางอยู่หน้าโมเดลทุกตระกูลใน เวิร์กช็อปนี้ (Anthropic, OpenAI, Google, DeepSeek, Qwen, Z.ai) แทนที่จะต้องเล่นกับ SDK ของผู้ให้บริการหกชุดและ credential หกชุด agent core (agents/) คุยผ่าน client ตัวเดียวเพื่อเข้าถึงทั้งหกโมเดลใน config.yaml นั่นคือสิ่งที่ทำให้การ แข่งขันที่ยุติธรรมและเทียบกันได้ตรง ๆ ในโมดูล 01 เป็นไปได้: ทุก โมเดลอยู่ห่างไปแค่สตริง model= เดียว หลัง endpoint เดียวกัน รูปแบบ request เดียวกัน
  • ClickHouse — ฐานข้อมูลของแอปพลิเคชัน มันเก็บข้อมูลธุรกิจ (ตาราง e-commerce สังเคราะห์ที่คุณกำลังจะ seed) อยู่หลัง view v_* agent ได้รับอนุญาต ให้ SELECT จาก view v_* เท่านั้น — ไม่ใช่ตารางดิบ ไม่มีการเขียน — ทั้งเพราะ นั่นเป็นสัญญาแบบอ่านอย่างเดียวที่เสถียรและมีเอกสารกำกับให้ agent ใช้คิด และเพราะ agents/sqlguard.py บังคับใช้มันเป็น sandbox ที่ทำได้แค่ SELECT: มัน parse SQL ที่ถูกสร้างขึ้นและปฏิเสธอะไรที่ไม่ใช่คำสั่ง SELECT/WITH…SELECT เดี่ยว ๆ และบล็อกรายชื่อคีย์เวิร์ดเขียน/DDL ที่ห้ามไว้ (INSERT, UPDATE, DELETE, DROP, ALTER, SYSTEM, …) แม้จะอยู่ในคำสั่งที่ถูกต้องตามหลักอย่างอื่นก็ตาม
  • Langfuse — ที่เก็บ eval, leaderboard และ observability มันถูกเชื่อมต่อตอนนี้ ก่อนที่คุณจะ เลือกโมเดลหรือถามคำถามแม้แต่ข้อเดียว เพราะมันไม่ใช่ของแปะเพิ่มไว้ทำภายหลัง — มันคือเครื่องมือที่ให้คะแนนการแข่งขันในโมดูล 01 ให้คุณเจาะลึกเรื่องคุณภาพใน โมดูล 02 และเฝ้าดู production ในโมดูล 04 โปรเจกต์เดียว ร่องรอยต่อเนื่องหนึ่งเส้นของ traces และ datasets ตั้งแต่การเลือกโมเดลครั้งแรกเป็นต้นไป

ภาพหน้าจอ: หน้า Settings → API Keys ของโปรเจกต์ Langfuse Cloud แสดงว่า คู่ public/secret key ที่คุณวางลงใน .env มาจากไหน — จับภาพจาก UI จริง

หลุมพราง — OPENROUTER_API_KEY ที่เป็น placeholder .env.example มาพร้อม OPENROUTER_API_KEY=sk-or-... เป็นแม่แบบ ไม่ใช่ key จริง ถ้าคุณลืมเขียนทับมัน การเรียกโมเดลทุกครั้งใน โมดูล 01 จะล้มเหลวด้วย auth error ของ OpenRouter ไม่ใช่ error ของ ClickHouse หรือ Langfuse — ดังนั้น ให้เช็ก .env ก่อนถ้าคุณเห็นอาการนั้น

หลุมพราง — host หรือ region ของ ClickHouse ผิด CLICKHOUSE_CLOUD_HOST ต้องเป็น host ที่ตรงเป๊ะจากรายละเอียดการเชื่อมต่อของ service ของคุณ (เจาะจงตาม region เช่น abc123.us-east-1.aws.clickhouse.cloud) ไม่ใช่โดเมนทั่วไป clickhouse.cloud host ที่ไม่ตรงจะล้มเร็วด้วย error ของ DNS/การเชื่อมต่อระหว่าง scripts/arena.sh up — นั่นคือลายเซ็นที่ต้องจำให้ได้

หลุมพราง — ARENA_RO_PASSWORD ไม่ตรงกัน scripts/arena.sh up สร้างผู้ใช้แบบอ่านอย่างเดียว arena_ro โดยใช้ค่าที่ ARENA_RO_PASSWORD ตั้งไว้ ณ ขณะนั้น ถ้าคุณ เปลี่ยนค่าใน .env ภายหลังโดยไม่รันการตั้งค่าใหม่ (หรือไม่ลบแล้วสร้าง ผู้ใช้ขึ้นใหม่) การเชื่อมต่อแบบอ่านอย่างเดียวของ agent จะเริ่ม authenticate ไม่ผ่าน แม้ว่า .env จะ "ดูถูกต้อง" ก็ตาม

เป้าหมาย

credential สามชุดใน .env, ฐานข้อมูล arena ที่ seed แล้วพร้อม view v_* ที่ agent จะ query และ dashboard ในเครื่องที่เข้าถึงได้จากเบราว์เซอร์

ขั้นที่ 1 — สร้างบัญชีสามบัญชี

คุณต้องมี API credential จากสามบริการก่อนจะแตะเทอร์มินัล:

บริการสิ่งที่คุณต้องมีหาได้จากที่ไหนตัวแปรใน .env
OpenRouterOPENROUTER_API_KEY หนึ่งตัวopenrouter.ai → Keys OpenRouter วางอยู่หน้าโมเดลทุกตระกูลที่ใช้ในเวิร์กช็อปนี้ (Anthropic, OpenAI, Google, DeepSeek, Qwen, Z.ai) ผ่าน API เดียวที่เข้ากันได้กับ OpenAIOPENROUTER_API_KEY, OPENROUTER_BASE_URL
Langfuse Cloudpublic + secret key ของโปรเจกต์cloud.langfuse.com → สร้างโปรเจกต์ → Settings → API KeysLANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_BASE_URL
ClickHouse Cloudhost, admin user, admin passwordclickhouse.com/cloud → สร้าง service → รายละเอียดการเชื่อมต่อCLICKHOUSE_CLOUD_HOST, CLICKHOUSE_CLOUD_USER, CLICKHOUSE_CLOUD_PASSWORD

เก็บทั้งสามอย่างไว้ใกล้ตัว — อีกเดี๋ยวคุณจะวางมันลงใน .env

ต้องตั้งค่าความเป็นส่วนตัวของ OpenRouter สำหรับ Qwen

ใน OpenRouter เปิด Settings → Privacy → Data Policies → Zero Data Retention แล้ว ปิด Non-frontier (toggle ต้องเป็นสีเทา/ปิด) Qwen อยู่ในกลุ่มโมเดล non-frontier ของ OpenRouter และ endpoint ของ Alibaba ที่มีให้ใช้จะไม่เข้าเกณฑ์เมื่อ บังคับใช้ Zero Data Retention สำหรับ non-frontier ถ้ายังเปิดค่านี้ไว้ qwen/qwen3.7-flash จะล้มเหลวด้วย No endpoints available matching your guardrail restrictions and data policy แม้ API key และ model slug จะถูกต้องก็ตาม

เวิร์กช็อปนี้ส่งคำถามและ schema ของ e-commerce สังเคราะห์ สำหรับงานจริง ให้ทบทวนข้อกำหนดความเป็นส่วนตัวขององค์กรคุณก่อนจะผ่อนปรนนโยบาย ZDR

ขั้นที่ 2 — Clone repo

Agent Arena อยู่ใน monorepo ClickHouse_Demos ภายใต้ workshops/agent_arena บน branch build-workshop-v1 Clone ทั้ง repo แล้วเข้าไปในไดเรกทอรีย่อยนั้น — ทุกคำสั่งจากนี้ไป สมมติว่าคุณยืนอยู่ในนั้น:

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

ขั้นที่ 3 — สร้าง virtualenv และติดตั้ง dependency

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

ขั้นที่ 4 — ตั้งค่า .env

คัดลอกไฟล์ตัวอย่าง:

cp .env.example .env

.env

กรอกค่าจากขั้นที่ 1 — ทุกค่าด้านล่างเป็นค่าว่างหรือ placeholder ใน .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-...

แต่ละบล็อกมีไว้ทำอะไร:

  • CLICKHOUSE_CLOUD_* — credential ของ admin ใน ClickHouse Cloud service ของคุณ การตั้งค่าใช้ admin user เพียงครั้งเดียว เพื่อสร้างฐานข้อมูล arena และผู้ใช้ แบบอ่านอย่างเดียว เฉพาะทาง (arena_ro) ที่ agent จะ query ผ่านตลอดส่วนที่เหลือของเวิร์กช็อป
  • ARENA_RO_PASSWORD — เลือกรหัสผ่านอะไรก็ได้; มันจะกลายเป็นรหัสผ่านของ arena_ro เมื่อ ผู้ใช้แบบอ่านอย่างเดียวถูกสร้างขึ้น
  • OPENROUTER_* — key ของ OpenRouter ของคุณและ base URL ของมัน ทุกโมเดลใน config.yaml ถูก เรียกผ่าน endpoint เดียวนี้
  • LANGFUSE_* — host และ key ของโปรเจกต์ Langfuse Cloud ของคุณ นี่คือที่ที่ trace, score และ dataset ทุกอย่างในเวิร์กช็อปอยู่ ตั้งแต่การรัน Arena ครั้งแรกในโมดูล 01 ไปจนถึง production ในโมดูล 04

ขั้นที่ 5 — Seed ClickHouse ด้วยข้อมูล e-commerce สังเคราะห์

ขั้นนี้สร้างฐานข้อมูล arena, ผู้ใช้แบบอ่านอย่างเดียว arena_ro, สร้างข้อมูล e-commerce สังเคราะห์ (customers, products, orders, order items, events) ลงใน ClickHouse โดยตรง และสร้าง view v_* ที่ agent จะ query:

source .env && scripts/arena.sh up

ทุก agent, prompt และ golden SQL ทุกชิ้นในเวิร์กช็อปนี้ query view v_customers, v_products, v_orders, v_order_items และ v_events — ไม่เคย query ตารางดิบ

scripts/arena.sh up ยังเริ่ม dashboard API และ web UI ในเครื่องด้วย เมื่อ มันเสร็จ ให้เปิด http://localhost:5174 — แท็บ Leaderboard จะว่างจนกว่า คุณจะรันการแข่งขันในโมดูล 01

การรันที่สมบูรณ์หน้าตาเป็นอย่างไร scripts/arena.sh up พิมพ์ตามลำดับนี้:

  1. ClickHouse: business database + read-only agent user — ฐานข้อมูล arena และ ผู้ใช้ arena_ro เฉพาะทางถูกสร้างขึ้น
  2. Seeding ClickHouse directly + views + schema context — บรรทัด clickhouse: inserted <N> into <table> หนึ่งบรรทัดต่อหนึ่งตาราง (customers, products, orders, order_items, events) แล้วตามด้วย done แล้ว view v_* และ schema context ที่ agent อ่านจะถูกสร้าง
  3. Starting dashboard API (:8000) + web UI (:5174) — บรรทัด [ready] สองบรรทัด ถ้าอันใด บอกว่า [NOT up] แปลว่าพอร์ตนั้นน่าจะถูกใช้อยู่แล้ว; ตรวจดู path ของ log ที่มันพิมพ์ (.run/dashboard-api.log หรือ .run/web.log)

เอาต์พุตในเทอร์มินัลแสดง dashboard API ของ Agent Arena พร้อมใช้งานบนพอร์ต 8000 และ web UI พร้อมใช้งานบนพอร์ต 5174

dashboard ของ Agent Arena ตอนโหลดครั้งแรก โดยที่ Leaderboard ว่างเปล่าและไม่มีข้อมูลการรัน

คุณตรวจสอบสิ่งเหล่านี้ซ้ำได้ภายหลังด้วย scripts/arena.sh status ซึ่งจะพิมพ์ว่า เซิร์ฟเวอร์ขึ้นอยู่หรือไม่ และจำนวนแถวของแต่ละ view v_*

วิธีตรวจสอบว่าคุณทำเสร็จแล้ว

  • .env มีค่าจริง (ไม่ใช่ placeholder) สำหรับ CLICKHOUSE_CLOUD_*, OPENROUTER_* และ LANGFUSE_*
  • scripts/arena.sh up ทำงานจนจบโดยไม่มี error
  • http://localhost:5174 โหลดได้ในเบราว์เซอร์ แสดงแท็บ Leaderboard (ว่างเปล่าถือว่า ถูกต้องในตอนนี้)

แบบฝึกหัด — ทำให้การเชื่อมต่อพังแล้ววินิจฉัย

เรียนรู้ที่จะจำค่า .env ที่พังได้จากลายเซ็นความล้มเหลวของมัน โดยทำอย่างตั้งใจในขณะที่ ยังไม่มีอะไรต้องเสีย:

  1. เปิด .env แล้วเปลี่ยนตัวอักษรหนึ่งตัวใน ARENA_RO_PASSWORD (หรือคอมเมนต์มัน ออกชั่วคราว)
  2. รัน source .env && scripts/arena.sh up ใหม่ มันควรจะยังผ่านขั้นตอน ClickHouse admin ได้ (พวกนั้นใช้ credential ของ admin) แต่ให้จับตาว่า เส้นทางแบบอ่านอย่างเดียว — อะไรที่เชื่อมต่อในฐานะ arena_ro — เริ่มร้องตรงไหน
  3. อ่านข้อความ error ให้ละเอียด: มันเป็น authentication error, error แบบ "user does not exist" หรือความเงียบแล้วตามด้วย timeout? จดไว้ว่าคุณได้อันไหน
  4. คืนค่า ARENA_RO_PASSWORD ที่ถูกต้องแล้วรัน scripts/arena.sh up ใหม่ ยืนยันว่ามัน ทำงานจนจบอย่างสะอาดอีกครั้ง

นี่คือสัญชาตญาณการวินิจฉัยแบบเดียวกับที่คุณจะอยากมีภายหลังเมื่อการตั้งค่าของเพื่อนร่วมทีม "ไม่ ทำงาน" — จับคู่ข้อความ error กับว่าบริการไหนในสามบริการที่ตั้งค่าผิด แทนที่จะไปตรวจซ้ำทุกอย่าง

สรุปปิดท้าย

คุณมีฐานข้อมูล ClickHouse ที่ seed แล้ว credential ของทั้งสามบริการ — รวมถึง Langfuse ที่เชื่อมต่อไว้ก่อนจะเลือกโมเดลใด ๆ — และ dashboard ในเครื่องที่รันอยู่ ทุกอย่างหลังโมดูลนี้ใช้สภาพแวดล้อมเดียวกันนี้และโปรเจกต์ Langfuse เดียวกันนี้ซ้ำ; ไม่มีขั้นตอนการตั้งค่าเพิ่มอีก

สถานะสุดท้าย

สภาพแวดล้อมพร้อมแล้ว ไปต่อที่ 01 เลือกโมเดลฐาน เพื่อรันการแข่งขันกับข้อมูล ชุดนี้

ในหน้านี้

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.

TH