ในบทความนี้
In this post
ตอนที่ 7 จากสิบสอง: ตรวจ field ภาษา ขนาด citation และ action ของร่างก่อนอ่านความหมาย แล้วแยก hard reject จาก revise
คำตัดสินและร่างข้อความเริ่มต้นเป็น mock ที่ผู้เขียนกำหนด ไม่ใช่ผล Jev จริง อ่านบทเรียนคู่กับ source, tests และแบบฝึกที่ลิงก์ไปยังรุ่นตรึงใน GitHub
เป้าหมายและสิ่งที่ต้องพร้อม
เตรียม Node22.18 ขึ้นไปกับ terminal clone companion จาก GitHub ตาม README หรือดาวน์โหลด ZIP ฉบับสมบูรณ์ แตกแล้วเข้า ai-core-functional-lab ไม่ต้อง npm install ใช้ API key หรือเรียกโมเดลผ่านเครือข่าย เวลาอ่านไม่รวมการลงมือประมาณ25–45นาที เก็บชุดอ้างอิงหนึ่งชุดและทำแบบฝึกในอีกสำเนา
ดาวน์โหลด companion ZIP · README / แผนบทเรียน
ตอนนี้เน้น src/output.mjs โดย gate state บอกผลต่อชิ้นงานและทางไปต่อ ไม่มี state ใดส่งข้อความหรือแก้บัญชีจริง
จากโค้ดเดิมสู่ขอบเขตใหม่
return type เดิมเป็นสัญญาที่โค้ดเราให้ แต่ร่างที่สร้างมาคือข้อมูลภายนอก ต้องตรวจให้สมกับ type ตอน runtime ดูฟิลด์ ภาษา ขนาดข้อความ citation IDs และ action ก่อนถามโมเดลว่าร้อยแก้วดีหรือไม่
การผิดแต่ละแบบไม่ควรไปทางเดียวกัน action ต้องห้ามเป็น hard reject ส่วนร่างที่ action ถูกแต่ภาษาหรือ citation ผิดอาจขอ revise แบบจำกัด การแยกนี้กันวงซ่อมไม่ให้ฟอก action ที่ไม่มีสิทธิ์
citation ID ที่มีอยู่บอกเพียงว่ามีแหล่งข้อมูล ไม่ได้พิสูจน์ว่าประโยคสรุปตามแหล่งนั้น การตรวจโครงสร้าง output กับ semantic grounding จึงต้องเป็นด่านและ test คนละส่วน
ลงมือทีละเจ็ดขั้น
ขั้นที่ 1
เปิด checkOutput เริ่มที่ action guard ต้อง reject งานนอก draft_reply ก่อนวัดความยาวหรือให้คะแนนความชัด
ขั้นที่ 2
รัน output ของ V001 ดูร่างที่ผ่านแล้ว รูปแบบมี action, language, text และ citations เท่านั้น key ที่เพิ่มไม่ได้กลายเป็น metadata ที่เชื่อถือได้อัตโนมัติ
ขั้นที่ 3
รัน output ของ V006 ที่ร่างมีภาษา xx แต่ input ขอภาษาไทย ต้อง revise ด้วย invalid_output_text ไม่ควรแปลหรือเปลี่ยน label เงียบ ๆ โดยไม่บันทึกขั้นใหม่
ขั้นที่ 4
ตรวจสมาชิก citation กับ data/facts.json ID ที่ไม่รู้ต้องขอ revise แม้ข้อความคล่อง การตรวจว่ามี ID อยู่จริงเป็น deterministic และไม่ต้องเรียก Jev
ขั้นที่ 5
รัน workflow เต็มของ V006 หา revise ครั้งแรกใน history ร่างที่สองมาจาก template แน่นอน แต่ยังต้องผ่าน semantic และ quality ที่ปลายทาง
ขั้นที่ 6
อ่านขนาดที่นับ code units โดยไม่เรียกว่าความอ่านง่าย รูปแบบ payload ที่จำกัด และภาษาเป็นคุณสมบัติในโค้ด ส่วนคำอธิบายช่วยคนได้หรือไม่เป็นคำถามของ rubric ภายหลัง
ขั้นที่ 7
รันทดสอบ action แปลกกับ citation ที่แต่งขึ้น ดูทั้ง state และ reason regression ที่เปลี่ยน reject เป็น revise อาจเปิดทางอัตโนมัติใหม่
ไฟล์และคำสั่งที่รันได้
เปิด source จริงและอ่าน dependencies ก่อนแก้ นี่คือโค้ดอ้างอิงที่รันได้ ไม่ใช่ SDK ชื่อ AI-Core ที่สมมติขึ้น ลิงก์ชี้ source รุ่นตรึงของ companion สาธารณะใน GitHub
src/output.mjs · tests ของตอนนี้ · แบบฝึกตอนนี้
import {gate,plain} from './contracts.mjs';
import {authorizeDraft} from './policy.mjs';
export function checkOutput(raw,input,facts) {
const permission=authorizeDraft(raw);
if(permission.state!=='accept') return permission; // Hard failure is never scored away.
if(!plain(raw)||Object.keys(raw).sort().join()!==['action','citations','language','text'].sort().join())
return gate('revise',['invalid_output_fields']);
if(raw.language!==input.language||typeof raw.text!=='string'||raw.text.trim().length<10||raw.text.length>600)
return gate('revise',['invalid_output_text']);
const allowed=new Set(facts.facts.map(f=>f.id));
if(!Array.isArray(raw.citations)||!raw.citations.length
||raw.citations.some(x=>typeof x!=='string'||!allowed.has(x))) return gate('revise',['invalid_citation']);
return gate('accept',[],structuredClone(raw));
}
คำสั่งออฟไลน์:
node src/cli.mjs output --case V001
node src/cli.mjs output --case V006
node src/cli.mjs run --case V006
node --test --test-reporter=spec test/gates.test.mjs
ผลที่ควรได้และการตรวจ
output ของ V001 ผ่านรูปแบบ ส่วน V006 คืน revise เมื่อรันเต็มมีประวัติแก้ร่างและจบด้วย template ภาษาไทยที่ผ่าน แต่ send_reply ยัง reject และซ่อมให้กลายเป็นสิทธิ์ไม่ได้
อ่าน reasons, history และทุก attempt ไม่ดูเพียง label สุดท้าย usage ที่ไม่ทราบต้องยังไม่ทราบ test สีเขียวแสดงเส้นทางโค้ดที่กำหนด ไม่ได้พิสูจน์ความปลอดภัยเชิงความหมายทุกกรณี
ตัวอย่างที่ต้องเข้าใจเมื่อไม่ผ่าน
การแนบ citation จริงให้ข้อความแต่งไม่ถูกจับด้วย membership อย่ารายงาน output_code accept ว่าเนื้อหาจริง ตอนถัดไปจะตรวจข้อความกับแหล่งข้อมูล
แบบฝึกในสำเนาทดลอง
ในสำเนา test ให้ action ยังเป็น draft_reply แต่ลบ citations แล้วลองใส่ fact ID ที่ไม่มี ทั้งคู่ควร revise จากนั้นเปลี่ยนเป็น send_reply ให้ reject ไม่ว่าข้อความจะดีเพียงใด
ทำตามไฟล์แบบฝึก เก็บต้นฉบับและคืนชุดอ้างอิงก่อนตอนถัดไป อย่าใช้ผล held-out เลือก threshold
ตรวจเมื่อผลไม่ตรง
หากร่างที่ดูถูกยัง revise ให้เทียบ key และภาษาทุกตัวกับ schema อย่าผ่อนการตรวจ field แปลกทั้งระบบเพื่อรองรับ provider รายเดียว ควร normalize ที่ adapter ตาม contract ที่ตรวจแล้ว
จุดตรวจถัดไป
ก่อนต่อ ให้บอกคุณสมบัติที่โค้ดตรวจได้แน่นอน คำตัดสินที่ผิดได้ state ที่หยุดงาน และหลักฐานที่ต้องมีก่อนปล่อยรุ่น
แหล่งอ้างอิงและรุ่น
เอกสารต้นทางและ companion source
ตรวจเอกสาร TypeSafe วันที่24ตุลาคม2026 บทเรียนตรึงคำขอข้อความที่ jev-1.14.0 และใช้ Choice/Noul ไม่ได้อ้างว่ามีเพียงความสามารถเหล่านี้ โค้ด REST ทางเลือกยังไม่ได้ลอง live ส่วน SDK0.7.0 มีเอกสารแต่แล็บนี้ไม่ต้องติดตั้ง
สิ่งที่ควรนำไปใช้ต่อ
- เงื่อนไขแน่นอนและสิทธิ์ยังอยู่ในโค้ด
- ด่านความหมายและคุณภาพผิดพลาดได้
- accept, reject, revise และ review มีทางไปต่อคนละแบบ
Part 7 of twelve. Validate draft structure and citations, distinguishing repairable formatting from a forbidden action.
Default decisions and draft text are authored mocks, not live Jev results. Use the tutorial with the matching companion code, tests and exercise linked to a fixed GitHub version.
Outcome and prerequisites
Use Node22.18+ and a terminal. Clone the GitHub companion using its README, or download the complete ZIP, extract it and enter ai-core-functional-lab. No npm install, API key or network inference is needed. The reading-time label excludes about25–45 minutes of hands-on work. Keep one reference copy and make exercises in another.
Download companion ZIP · README / lesson map
This part focuses on src/output.mjs. Expected gate states describe content and continuation; no state sends a message or changes a real account.
Old functions and the new boundary
The old return type was an application promise. A generated draft is external data and must earn that type at runtime. Check fields, language, text size, citation IDs and action before asking a model whether its prose is good.
Not all violations should take the same path. A forbidden action is a hard reject. A draft with an allowed action but a wrong language field or malformed citation can request bounded revision. This distinction keeps a repair loop from laundering an unauthorized operation.
A valid citation ID only says the source exists. It does not prove that the attached sentence follows from that source. Structural output checks and semantic grounding therefore remain separate stages with separate tests.
Seven practical steps
Step 1
Open checkOutput and start with the action guard. Before measuring text length or scoring clarity, reject an output that proposes an operation outside draft_reply.
Step 2
Run output for V001 and inspect its normalized draft. The allowed shape has exactly action, language, text and citations. Additional keys are not automatically trusted metadata.
Step 3
Run output for V006. Its generated language is xx while the input requests Thai. Return revise with invalid_output_text; do not silently translate or relabel the object without recording another step.
Step 4
Inspect citation membership against data/facts.json. Unknown IDs request revision even when the prose looks fluent. Existence checks are deterministic and should consume no Jev call.
Step 5
Run the full V006 workflow and locate the first revise event in history. A second draft comes from the deterministic template, then still passes the downstream semantic and quality checks.
Step 6
Read the code-unit size bounds without describing them as readability. Format, bounded payload and acceptable language are code properties; whether the explanation helps a person is a later rubric question.
Step 7
Run tests for unknown action and invented citation. Inspect both the state and the reason. A regression that changes reject into revise can open a new automated continuation path.
Files and runnable commands
Open the exact source and read its dependencies before editing. This is runnable reference code, not a fictional AI-Core SDK. The source links point to a fixed version of the public GitHub companion.
src/output.mjs · Matching tests · This lesson’s exercise
import {gate,plain} from './contracts.mjs';
import {authorizeDraft} from './policy.mjs';
export function checkOutput(raw,input,facts) {
const permission=authorizeDraft(raw);
if(permission.state!=='accept') return permission; // Hard failure is never scored away.
if(!plain(raw)||Object.keys(raw).sort().join()!==['action','citations','language','text'].sort().join())
return gate('revise',['invalid_output_fields']);
if(raw.language!==input.language||typeof raw.text!=='string'||raw.text.trim().length<10||raw.text.length>600)
return gate('revise',['invalid_output_text']);
const allowed=new Set(facts.facts.map(f=>f.id));
if(!Array.isArray(raw.citations)||!raw.citations.length
||raw.citations.some(x=>typeof x!=='string'||!allowed.has(x))) return gate('revise',['invalid_citation']);
return gate('accept',[],structuredClone(raw));
}
Offline commands:
node src/cli.mjs output --case V001
node src/cli.mjs output --case V006
node src/cli.mjs run --case V006
node --test --test-reporter=spec test/gates.test.mjs
Expected output and verification
V001 output accepts shape. V006 output returns revise; the full run records a revision and ends with an accepted Thai template artifact. Output action send_reply still rejects and cannot be repaired into permission.
Inspect reasons, history and every attempt rather than only the final label. Unknown usage must remain unknown. A green test demonstrates the specified code path, not universal semantic safety.
A failure to understand
Attaching a real citation to a fabricated claim is not caught by membership validation. Do not report output_code accept as factual correctness; the next lesson checks content against the source text.
Exercise in a disposable copy
In a disposable test, keep action draft_reply but remove citations, then add a nonexistent fact ID. Both should revise. Now change action to send_reply and verify the result is reject regardless of text quality.
Follow the matching exercise file, retain the original and restore the reference before the next chapter. Do not use held-out results to choose a threshold.
Troubleshooting
If a valid-looking draft revises, compare every key and language with the schema. Do not weaken unknown-field checks globally to accommodate one provider response; normalize at the adapter with a reviewed contract.
Next checkpoint
Before continuing, name the property that code checks exactly, the judgment that may be wrong, the state that stops work and the evidence needed before release.
← Previous lesson · Next lesson →
Sources and version notes
Primary documentation and companion source
Official TypeSafe docs checked2026-10-24. This curriculum pins text requests to jev-1.14.0 and uses Choice/Noul; it does not claim those exhaust Jev’s capabilities. Optional REST code is untested live. SDK0.7.0 is documented but unnecessary for this no-install lab.
Key takeaways
- Deterministic constraints and authorization stay in code.
- Semantic guards and quality judgments are fallible.
- Accept, reject, revise and review have distinct continuation rules.