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
ทำไม
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จาก viewv_*เท่านั้น — ไม่ใช่ตารางดิบ ไม่มีการเขียน — ทั้งเพราะ นั่นเป็นสัญญาแบบอ่านอย่างเดียวที่เสถียรและมีเอกสารกำกับให้ 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 |
|---|---|---|---|
| OpenRouter | OPENROUTER_API_KEY หนึ่งตัว | openrouter.ai → Keys OpenRouter วางอยู่หน้าโมเดลทุกตระกูลที่ใช้ในเวิร์กช็อปนี้ (Anthropic, OpenAI, Google, DeepSeek, Qwen, Z.ai) ผ่าน API เดียวที่เข้ากันได้กับ OpenAI | OPENROUTER_API_KEY, OPENROUTER_BASE_URL |
| Langfuse Cloud | public + secret key ของโปรเจกต์ | cloud.langfuse.com → สร้างโปรเจกต์ → Settings → API Keys | LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_BASE_URL |
| ClickHouse Cloud | host, admin user, admin password | clickhouse.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 พิมพ์ตามลำดับนี้:
ClickHouse: business database + read-only agent user— ฐานข้อมูลarenaและ ผู้ใช้arena_roเฉพาะทางถูกสร้างขึ้นSeeding ClickHouse directly + views + schema context— บรรทัดclickhouse: inserted <N> into <table>หนึ่งบรรทัดต่อหนึ่งตาราง (customers,products,orders,order_items,events) แล้วตามด้วยdoneแล้ว viewv_*และ schema context ที่ agent อ่านจะถูกสร้างStarting dashboard API (:8000) + web UI (:5174)— บรรทัด[ready]สองบรรทัด ถ้าอันใด บอกว่า[NOT up]แปลว่าพอร์ตนั้นน่าจะถูกใช้อยู่แล้ว; ตรวจดู path ของ log ที่มันพิมพ์ (.run/dashboard-api.logหรือ.run/web.log)


คุณตรวจสอบสิ่งเหล่านี้ซ้ำได้ภายหลังด้วย scripts/arena.sh status ซึ่งจะพิมพ์ว่า
เซิร์ฟเวอร์ขึ้นอยู่หรือไม่ และจำนวนแถวของแต่ละ view v_*
วิธีตรวจสอบว่าคุณทำเสร็จแล้ว
.envมีค่าจริง (ไม่ใช่ placeholder) สำหรับCLICKHOUSE_CLOUD_*,OPENROUTER_*และLANGFUSE_*scripts/arena.sh upทำงานจนจบโดยไม่มี errorhttp://localhost:5174โหลดได้ในเบราว์เซอร์ แสดงแท็บ Leaderboard (ว่างเปล่าถือว่า ถูกต้องในตอนนี้)
แบบฝึกหัด — ทำให้การเชื่อมต่อพังแล้ววินิจฉัย
เรียนรู้ที่จะจำค่า .env ที่พังได้จากลายเซ็นความล้มเหลวของมัน โดยทำอย่างตั้งใจในขณะที่
ยังไม่มีอะไรต้องเสีย:
- เปิด
.envแล้วเปลี่ยนตัวอักษรหนึ่งตัวในARENA_RO_PASSWORD(หรือคอมเมนต์มัน ออกชั่วคราว) - รัน
source .env && scripts/arena.sh upใหม่ มันควรจะยังผ่านขั้นตอน ClickHouse admin ได้ (พวกนั้นใช้ credential ของ admin) แต่ให้จับตาว่า เส้นทางแบบอ่านอย่างเดียว — อะไรที่เชื่อมต่อในฐานะarena_ro— เริ่มร้องตรงไหน - อ่านข้อความ error ให้ละเอียด: มันเป็น authentication error, error แบบ "user does not exist" หรือความเงียบแล้วตามด้วย timeout? จดไว้ว่าคุณได้อันไหน
- คืนค่า
ARENA_RO_PASSWORDที่ถูกต้องแล้วรันscripts/arena.sh upใหม่ ยืนยันว่ามัน ทำงานจนจบอย่างสะอาดอีกครั้ง
นี่คือสัญชาตญาณการวินิจฉัยแบบเดียวกับที่คุณจะอยากมีภายหลังเมื่อการตั้งค่าของเพื่อนร่วมทีม "ไม่ ทำงาน" — จับคู่ข้อความ error กับว่าบริการไหนในสามบริการที่ตั้งค่าผิด แทนที่จะไปตรวจซ้ำทุกอย่าง
สรุปปิดท้าย
คุณมีฐานข้อมูล ClickHouse ที่ seed แล้ว credential ของทั้งสามบริการ — รวมถึง Langfuse ที่เชื่อมต่อไว้ก่อนจะเลือกโมเดลใด ๆ — และ dashboard ในเครื่องที่รันอยู่ ทุกอย่างหลังโมดูลนี้ใช้สภาพแวดล้อมเดียวกันนี้และโปรเจกต์ Langfuse เดียวกันนี้ซ้ำ; ไม่มีขั้นตอนการตั้งค่าเพิ่มอีก
สถานะสุดท้าย
สภาพแวดล้อมพร้อมแล้ว ไปต่อที่ 01 เลือกโมเดลฐาน เพื่อรันการแข่งขันกับข้อมูล ชุดนี้