การใช้โมเดลภาษาขนาดใหญ่ (LLM) เพื่อแปลงคำอธิบายภาษาธรรมชาติเป็น SystemVerilog Assertion (SVA) โดยผิวเผินแล้วเป็นสาขาหนึ่งของ “การสร้างโค้ด” แต่ความท้าทายที่แท้จริงไม่ใช่ไวยากรณ์ แต่เป็นความหมาย (Semantics) ตัวอย่างเช่น ข้อกำหนดที่ว่า “ต้องตอบสนองหลังจากจับมือกัน” อาจเกี่ยวข้องกับการเลือกตรรกะที่ละเอียดอ่อนหลายอย่าง เช่น การนัยเชิงเวลา (temporal implication) การปิดกั้นสัญญาณรีเซ็ต ความเสถียรของสัญญาณ หน้าต่างหน่วงเวลา และนามธรรมระดับบิต
งานวิจัยเผยให้เห็นว่า ในงาน Natural Language to SVA (NL-to-SVA) ข้อผิดพลาดด้านฟังก์ชันมากกว่า 80% เกิดจากการใช้ตัวดำเนินการเชิงเวลา (temporal operators) ผิดวิธี โดยเฉพาะอย่างยิ่ง ความสับสนระหว่างตัวดำเนินการ |-> และ |=> เพียงสองตัวนี้ทำให้ assertion ใช้ไม่ได้ผลถึง 50% ถึง 64% ข้อผิดพลาดประเภทนี้มีความคล้ายคลึงกันสูงในระดับข้อความ แต่กลับให้ผลลัพธ์การตรวจสอบเชิงรูปแบบ (formal verification) ที่ตรงกันข้ามโดยสิ้นเชิง
เมื่อเผชิญกับงาน NL-to-SVA การอนุมานทั่วไปของ LLM มักจะสร้าง SVA ที่มีข้อผิดพลาดด้านฟังก์ชัน เฟรมเวิร์ก FVRULELEARNER จาก NVlabs ใช้แนวทางที่แตกต่าง โดยสร้าง SVA ที่ถูกต้องตามฟังก์ชันผ่านแผนผังการอนุมานตัวดำเนินการ (OP-TREE) ที่เรียนรู้ได้ รูปภาพด้านล่างแสดงให้เห็นถึงความแตกต่างระหว่าง LLM ทั่วไปกับ FVRULELEARNER ในการสร้าง SVA โดยชี้ให้เห็นถึงปัญหาข้อผิดพลาดด้านฟังก์ชันของ LLM ในงาน NL-to-SVA ซึ่งเกิดจากความเข้าใจที่ไม่เพียงพอเกี่ยวกับตัวดำเนินการเชิงเวลาและข้อมูลการฝึกอบรมที่จำกัด LLM ทั่วไปไม่สามารถจับคู่ความหมายเชิงเวลาของฮาร์ดแวร์ได้อย่างแม่นยำ ในขณะที่ FVRULELEARNER อาศัยการอนุมานเชิงโครงสร้างของแผนผังการอนุมานตัวดำเนินการ ยึดโยงกับตรรกะการใช้งานที่ถูกต้องของตัวดำเนินการ SVA และแก้ไขปัญหาความไม่ตรงกันของฟังก์ชันตั้งแต่ต้นตอ สิ่งนี้ยืนยันคุณค่าหลักของ OP-TREE ในการปรับปรุงความถูกต้องของฟังก์ชัน SVA และยังเป็นรากฐานของนวัตกรรมทางเทคนิคของเฟรมเวิร์กนี้
เมื่อ LLM เขียน |-> ผิดเป็น |=> หรือละเว้นเงื่อนไข enable บางอย่าง แม้ว่าความคล้ายคลึงกันของข้อความอาจยังสูงอยู่ แต่ผลลัพธ์ของการตรวจสอบเชิงรูปแบบจะแตกต่างกันอย่างมาก
- FVRULELEARNER: Operator-Level Reasoning Tree (OP-TREE)-Based Rules Learning for Formal Verification
- FVRuleLearner คือไปป์ไลน์การเรียนรู้กฎสำหรับ NL2SVA เวอร์ชันหลักที่เผยแพร่ในปัจจุบันคือเส้นทางแบบ prompt-only ในไดเรกทอรี
srcและใช้ JasperGold ในการประเมินไวยากรณ์และฟังก์ชัน - โค้ด: https://github.com/NVlabs/FVRuleLearner
- บทความ: https://arxiv.org/abs/2604.03245
คุณค่าหลักของ NVlabs/FVRuleLearner คือการเปลี่ยนตัวอย่างที่ล้มเหลวจากข้อผิดพลาดครั้งเดียว ให้กลายเป็นสินทรัพย์กฎที่สามารถนำไปค้นหา จัดลำดับ อธิบาย และนำกลับมาใช้ใหม่ได้ในภายหลัง
ภาพรวมของกระบวนการ FVRULELEARNER และตัวอย่างของ OP-TREE ระหว่างการฝึกอบรมแสดงอยู่ในรูปด้านล่าง รูปภาพนี้แยกย่อยกระบวนการหลักสองขั้นตอนของการฝึกอบรมและการทดสอบของ FVRULELEARNER: ขั้นตอนการฝึกอบรมจะจำลองตรรกะการดีบักของวิศวกรตรวจสอบผ่านโครงสร้างสามชั้นของ OP-TREE เพื่อกลั่นกรองร่องรอยการอนุมานตัวดำเนินการที่มีประสิทธิภาพ ขั้นตอนการทดสอบจะจับคู่ร่องรอยผ่านการค้นหาแบบผสมระหว่างตัวดำเนินการและความหมาย หลังจากปรับกฎแล้ว จะสร้าง Op-Rule สำหรับงานใหม่ OP-TREE ทำให้กระบวนการอนุมานสามารถอธิบายได้ แก้ปัญหากล่องดำของ LLM ในการสร้าง SVA ในขณะที่การออกแบบสองขั้นตอนช่วยรับประกันประสิทธิผลของกฎและความสามารถในการสรุปข้ามงาน
เฟรมเวิร์กนี้ไม่ได้เป็นเพียงการซ้อน prompt อย่างง่าย ๆ แต่เป็นการสร้าง OP-Tree สามชั้นในขั้นตอนการฝึกอบรม เจาะลึกถึงสาเหตุของข้อผิดพลาด ผ่านการวินิจฉัยบริบท การยึดโยงทางทฤษฎี และการสร้างกฎ เพื่อสร้างกฎระดับตัวดำเนินการที่ตรวจสอบได้ โดยคงไว้เฉพาะเส้นทางการอนุมานที่ JasperGold ยืนยันว่ามีฟังก์ชันเทียบเท่า ในขั้นตอนการอนุมานจะใช้กลไก RAG ที่ให้คะแนนแบบผสมระหว่างตัวดำเนินการและความหมาย ควบคู่กับการปรับกฎตามนามธรรมของสัญญาณ เพื่อสร้าง assertion ที่แม่นยำ
รูปภาพด้านล่างเปรียบเทียบผลกระทบของกฎทั่วไปกับกฎระดับตัวดำเนินการต่อการสร้าง SVA กฎทั่วไปเนื่องจากความเป็นนามธรรม ไม่สามารถแนะนำ LLM ให้ใช้ตัวดำเนินการเชิงเวลาได้อย่างแม่นยำ และสุดท้ายจะสร้าง assertion ที่มีข้อผิดพลาดด้านฟังก์ชัน ในขณะที่ Op-Rule ซึ่งเป็นคำสั่งที่ละเอียดและสามารถดำเนินการได้สำหรับตัวดำเนินการ SVA จะกำหนดสถานการณ์การใช้งานของตัวดำเนินการเชิงเวลาอย่างชัดเจน และขจัดความคลุมเครือทางความหมายโดยสิ้นเชิง การเปรียบเทียบนี้ยืนยันว่าความแม่นยำของกฎระดับตัวดำเนินการเป็นกุญแจสำคัญในการแก้ไขข้อบกพร่องด้านความหมายเชิงเวลาของ LLM และเป็นนวัตกรรมหลักที่ทำให้ FVRULELEARNER แตกต่างจากการเรียนรู้กฎแบบดั้งเดิม
ข้อมูลการทดลองแสดงให้เห็นว่า เมื่อเทียบกับ SOTA baseline เฟรมเวิร์กนี้มีความถูกต้องทางไวยากรณ์เพิ่มขึ้น 3.95% ความถูกต้องทางฟังก์ชันเพิ่มขึ้นโดยเฉลี่ย 31.17% และข้อผิดพลาดด้านฟังก์ชันของตัวดำเนินการต่างๆ ลดลงโดยเฉลี่ย 70.33% นอกจากนี้ ยังต้องการข้อมูลการฝึกอบรมเพียง 48% เพื่อให้ถึงจุดอิ่มตัวของประสิทธิภาพ และเปิดเผยชุดข้อมูลมาตรฐาน NL2SVA-OpenCore ที่มี 1,000 รายการจากการออกแบบฮาร์ดแวร์จริง
ตารางด้านล่างแสดงผลการทดลองของโมเดล LLM บนชุดทดสอบ NL-to-SVA สามประเภท เมื่อเปรียบเทียบ GPT-4o, Claude 4.5 Sonnet, o3-mini ภายใต้ baseline ต่างๆ และ FVRULELEARNER ในด้าน BLEU, ความถูกต้องทางไวยากรณ์, ความถูกต้องทางฟังก์ชัน ฯลฯ FVRULELEARNER มีประสิทธิภาพเหนือกว่าอย่างมากในทุกโมเดลและทุกชุดข้อมูล โดยความถูกต้องทางฟังก์ชันเพิ่มขึ้นโดยเฉลี่ย 31.17% และความถูกต้องทางไวยากรณ์ใกล้เคียง 100% ผลลัพธ์พิสูจน์ให้เห็นว่าเฟรมเวิร์กนี้ไม่พึ่งพา LLM เฉพาะเจาะจง มีความสามารถในการปรับใช้ได้ทั่วไปอย่างมาก และสามารถชดเชยข้อบกพร่องทางความหมายของ LLM ต่างๆ ในการสร้าง SVA ได้อย่างครอบคลุม
สารบัญ
- หนึ่ง. การเริ่มต้นใช้งานอย่างรวดเร็ว
- สอง. ปัญหาหลักที่โครงการต้องแก้ไข: การสร้าง SVA ไม่ใช่การแปล แต่เป็นการจัดตำแหน่งความหมายที่ตรวจสอบได้
- 2.1 ช่องว่างทางความหมายจากภาษาธรรมชาติสู่ assertion เชิงรูปแบบ
- 2.2 ภารกิจสามประเภทและจุดเริ่มต้นข้อมูล
- สาม. สถาปัตยกรรมโดยรวม: การฝึกอบรมตกตะกอนกฎ การอนุมานค้นหากฎ การประเมินปิดลูปการตรวจสอบ
- 3.1 จุดเริ่มต้นหลักคือเครื่องสถานะ
- 3.2 การกำหนดค่าไม่ใช่สิ่งประกอบ แต่เป็นโปรโตคอลการทดลอง
- สี่. Q-Tree: แยกข้อผิดพลาดครั้งเดียวเป็นเส้นทางการอนุมานที่เรียนรู้ได้
- 4.1 ทำไมต้องเป็นต้นไม้ ไม่ใช่แค่ข้อความสะท้อน
- 4.2 กระบวนการสร้าง Q-Tree
- ห้า. RAG และการค้นหาเสริม: ไม่ใช่การหาคำตอบที่คล้ายกัน แต่เป็นการหาประสบการณ์การแก้ไขข้อผิดพลาดที่คล้ายกัน
- 5.1 RAGAgent จัดระเบียบเอกสารอย่างไร
- 5.2 จุดเริ่มต้นของการค้นหาเสริมด้วย Q-Tree
- หก. การจัดเตรียม LLM: เส้นทางแบบเบาและเส้นทาง AutoGen อยู่ร่วมกัน
- 6.1 FVProcessor คือตัวจัดตารางไปป์ไลน์
- 6.2 กฎเข้าสู่ prompt อย่างไร
- เจ็ด. ลูปปิด JasperGold: ข้อความที่เหมือนกันไม่ได้หมายความว่าฟังก์ชันถูกต้อง
- 7.1 สคริปต์ Tcl กำหนดความหมายของการประเมินรูปแบบ
- 7.2 ผลลัพธ์การประเมินถูกรวบรวมอย่างไร
- แปด. ทรัพยากร SystemVerilog: testbench ไม่ใช่พื้นหลัง แต่เป็นจุดยึดทางความหมาย
- 8.1 annotated_tb รองรับบริบทการตรวจสอบ
- 8.2 ความพิเศษของเส้นทาง opencore
- เก้า. ความรู้ถูกจัดเก็บอย่างไร: suggestions และ qtrees คือความทรงจำระยะยาวของโครงการ
- 9.1 Q-Tree ถูกบันทึกในรูปแบบที่ทั้งเครื่องจักรและมนุษย์อ่านได้
- 9.2 ความแตกต่างพื้นฐานจาก RAG ทั่วไป
- สิบ. ข้อจำกัด ขอบเขต และสิ่งที่ควรนำไปปรับใช้
- 10.1 ข้อจำกัดที่ต้องกล่าวถึงอย่างระมัดระวัง
- 10.2 แรงบันดาลใจสำหรับระบบ AI+EDA
- 10.3 หากเปรียบเทียบกับคอมไพเลอร์
- บทสรุป: ความก้าวหน้าที่แท้จริงคือการทำให้ประสบการณ์การตรวจสอบเชิงรูปแบบสามารถสะสมได้
หนึ่ง. การเริ่มต้นใช้งานอย่างรวดเร็ว
เส้นทางหลักของโครงการและการเริ่มต้นใช้งานอย่างรวดเร็ว
เส้นทางหลักของ FVRuleLearner เวอร์ชันที่เผยแพร่ในปัจจุบันเป็นไปตามโหมด prompt-only ที่อธิบายไว้ใน README โดยจุดเริ่มต้นของโค้ดจะรวมอยู่ในไดเรกทอรี src/ ซึ่ง主要负责สามภารกิจหลัก: nl2sva_human, nl2sva_machine และ nl2sva_opencore ต่อไปนี้เป็นขั้นตอนมาตรฐานสำหรับการตั้งค่าสภาพแวดล้อมการทำงานอย่างรวดเร็ว:
# ที่มา: README.md
conda create -n fvrulelearner python=3.10
conda activate fvrulelearner
pip install -r requirements.txt
ก่อนเริ่มทำงาน ต้องกำหนดค่าอินเทอร์เฟซ LLM และตัวแปรสภาพแวดล้อมของเครื่องมือตรวจสอบเชิงรูปแบบ JasperGold:
# ที่มา: README.md
export OPENAI_API_KEY=...
# หรือ: export ANTHROPIC_API_KEY=...
export PATH=/path/to/jasper/bin:$PATH
export LM_LICENSE_FILE=<your_jasper_license_server>
export CDS_LIC_FILE=<your_jasper_license_server>
รันคำสั่งต่อไปนี้ในไดเรกทอรีรากของ repository เพื่อเริ่มกระบวนการหลัก:
# ที่มา: README.md
cd FVRuleLearner
python3 src/main.py
พารามิเตอร์หลักทั้งหมดจะรวมอยู่ในไฟล์ src/config.py ขั้นตอนการฝึกอบรมต้องกำหนดค่าดังนี้:
# ที่มา: src/config.py
# เลือกขั้นตอนการดำเนินการ: train / inference / eval
# global_task = 'inference'
global_task = 'train'
# global_task = 'eval'
# ภารกิจที่เผยแพร่ที่รองรับ:
# task = "nl2sva_human"
# task = "nl2sva_machine"
task = "nl2sva_opencore"
LLM_gateaway = "openai"
# LLM_gateaway = "claude"
llm_model = 'gpt-4o'
# llm_model = "claude-sonnet-4-5-20250929"
เมื่อการฝึกอบรมเสร็จสิ้น ผลลัพธ์จะถูกจัดเก็บในโครงสร้างไดเรกทอรีต่อไปนี้:
# ที่มา: README.md
src/logs/train_<timestamp>_<hostname>_<user>/
suggestions.pkl
qtrees.pkl
qtrees.json
log.txt
FLAGS.klepto
เมื่อต้องการทำการอนุมาน เพียงเปลี่ยน global_task เป็น "inference" และชี้ load_suggestions_path ไปยังไดเรกทอรีบันทึกที่สร้างจากการฝึกอบรมครั้งก่อน นอกจากนี้ ยังสามารถตั้งค่าตัวแปรสภาพแวดล้อม FVRULELEARNER_TRAIN_LOGDIR เพื่อแทนที่เส้นทางบันทึกเริ่มต้น สำหรับข้อมูลเกี่ยวกับความสัมพันธ์ของชุดข้อมูล การกำหนดค่าพารามิเตอร์ที่แนะนำ และวิธีการใช้งานแบบประเมินเท่านั้น (eval-only) โปรดดูเอกสาร README ฉบับเต็มของ repository: https://github.com/NVlabs/FVRuleLearner/blob/main/README.md
สอง. ความท้าทายหลัก: การสร้าง SVA ไม่ใช่แค่การแปลง่ายๆ แต่เป็นการจัดตำแหน่งความหมายที่ตรวจสอบได้
2.1 ช่องว่างทางความหมายระหว่างภาษาธรรมชาติกับ assertion เชิงรูปแบบ
เมื่อมองเผินๆ ภารกิจ NL2SVA ดูเหมือนจะเป็นการแปลงคำอธิบายภาษาธรรมชาติเป็นโค้ด SVA เช่น “เมื่อการเขียนมีผลและ FIFO ไม่เต็ม ตัวชี้เขียนควรได้รับการอัปเดต” อย่างไรก็ตาม ในบริบทที่เข้มงวดของการตรวจสอบเชิงรูปแบบ ประโยคนี้ซ่อนข้อจำกัดทางวิศวกรรมหลายชุดไว้เบื้องหลัง:
- assertion ควรสุ่มตัวอย่างตามขอบนาฬิกาใด
- จำเป็นต้องปิดการใช้งาน assertion นี้ระหว่างการรีเซ็ตหรือไม่
- ควรใช้ตัวดำเนินการ
|->หรือ|=>ระหว่าง antecedent และ consequent หรือไม่ - จำเป็นต้องแนะนำการดำเนินการเชิงเวลา เช่น
$stable,$pastหรือ##[n:m]หรือไม่ - สัญญาณที่เกี่ยวข้องมาจากชั้นนามธรรมของ testbench หรือจากโค้ด RTL ดั้งเดิม
- จะตัดสินความเท่าเทียมกันระหว่าง assertion อ้างอิงได้อย่างไร ไม่ใช่แค่ความคล้ายคลึงกันในระดับสตริง
บทความวิชาการของ FVRuleLearner มีชื่อว่า “Operator-Level Reasoning Tree (OP-Tree)-Based Rules Learning for Formal Verification” [1] ไฟล์ README ของ repository ระบุอย่างชัดเจนว่ามันคือไปป์ไลน์การเรียนรู้กฎที่ออกแบบมาสำหรับ NL2SVA โดยเฉพาะ และใช้ JasperGold ในการประเมินไวยากรณ์และฟังก์ชันอย่างครอบคลุม กล่าวคือ โครงการนี้ไม่พอใจแค่กับการ “สร้างโค้ดที่ดูเหมือน SVA” แต่เป้าหมายที่แท้จริงคือการเรียนรู้ “ว่าทำไม assertion หนึ่งถึงผิด และเมื่อพบรูปแบบตัวดำเนินการที่คล้ายกันอีกครั้ง ควรแก้ไขอย่างไร”
2.2 ภารกิจสามประเภทและจุดเริ่มต้นข้อมูล
ในไฟล์กำหนดค่า ภารกิจที่เผยแพร่จะถูกจำกัดอย่างเข้มงวดเป็นสามประเภทต่อไปนี้:
# ที่มา: src/config.py
if task == "nl2sva_human":
dataset_path = os.path.join(ROOT, "FVEval", "data_nl2sva", "data", "nl2sva_human.csv")
elif task == "nl2sva_machine":
dataset_path = os.path.join(ROOT, "FVEval", "data_nl2sva", "data", "nl2sva_machine_updated.csv")
elif task == "nl2sva_opencore":
dataset_path = os.path.join(ROOT, "FVEval", "data_1k", "module_sva_nl_manual_editing.csv")
else:
raise ValueError(f"Unsupported release task: {task}")
需要注意的是,该项目并非面向任意 Verilog 仓库的通用断言生成器,而是围绕特定基准测试格式组织起来的研究原型。每条数据记录通常包含自然语言提示、参考断言、设计名称、任务标识符、测试平台及相关上下文信息。
- Python 主控部分负责组织样本、调用 LLM 生成 SVA 并保存结果;
- FVEval 组件则负责将生成的结果与参考答案一同放入 JasperGold 可执行的评估框架中,进行闭环验证。
三. สถาปัตยกรรมโดยรวม: การฝึกอบรมตกตะกอนกฎ การอนุมานค้นหากฎ การประเมินปิดลูป
3.1 จุดเริ่มต้นหลักคือเครื่องสถานะ
3.1 ไปป์ไลน์สามขั้นตอน: การฝึกอบรม การอนุมาน และการประเมิน
โค้ดของ src/main.py แม้จะสั้น แต่ได้กำหนดกระบวนการหลักสามขั้นตอนของโครงการอย่างชัดเจน: train (การฝึกอบรม), inference (การอนุมาน) และ eval (การประเมิน)
# ที่มา: src/main.py
def main():
if FLAGS.global_task in ['inference', 'train']:
if FLAGS.model == 'agent':
start_time = time.time()
from fv_harwareagent_example import FVProcessor
processor = FVProcessor()
processor.main_fv()
saver.save_stats('overall_runtime', time.time()-start_time)
elif FLAGS.model == 'timing_agent':
from hardware_agent.examples.timing_summary_hardwareagent_example import main
main()
else:
raise NotImplementedError()
if FLAGS.global_task == 'inference':
from eval import eval
eval(Path(saver.logdir))
elif FLAGS.global_task == "eval":
from eval import eval
eval(FLAGS.folder_to_eval)
ตรรกะสำคัญมีดังนี้:
- การฝึกอบรมและการอนุมาน: ทั้งสองดำเนินการผ่านโมดูล
FVProcessorข้อแตกต่างเพียงอย่างเดียวคือหลังจากงานอนุมานเสร็จสิ้น จะเริ่มกระบวนการประเมินโดยอัตโนมัติ - ประเมินเท่านั้น: หากระบุ
global_taskเป็น"eval"ระบบจะประเมินประสิทธิภาพอีกครั้งโดยตรงกับไดเรกทอรีผลลัพธ์การอนุมานที่มีอยู่
การออกแบบนี้ก่อให้เกิดไปป์ไลน์สามขั้นตอนที่ชัดเจน:
# ที่มา: ย่อจาก src/main.py และ README
train:
ตัวอย่างชุดข้อมูล -> LLM สร้าง SVA -> เปรียบเทียบกับ assertion อ้างอิง -> Q-Tree สอบถามข้อผิดพลาด -> บันทึก suggestions.pkl/qtrees.json
inference:
prompt ใหม่ -> ค้นหาตัวอย่าง/suggestions/qtrees ที่คล้ายกัน -> LLM สร้างหรือแก้ไข SVA -> JasperGold แก้ไขไวยากรณ์ -> บันทึกผลลัพธ์
eval:
ไดเรกทอรีผลลัพธ์ LLM -> ประเมินความคล้ายคลึงข้อความ + ประเมินฟังก์ชัน JasperGold -> สรุปเป็น CSV
3.2 การกำหนดค่า: ไม่ใช่แค่สิ่งประกอบ แต่เป็น “โปรโตคอล” ของการทดลอง
ในไฟล์ src/config.py การกำหนดค่าสำหรับขั้นตอนการฝึกอบรมและการอนุมานถูกแยกออกจากกันอย่างชัดเจน ขั้นตอนการฝึกอบรมจะปิดการทำงาน RAG (Retrieval-Augmented Generation) และการประเมินหลักของ JasperGold โดยเน้นที่การสร้าง suggestion และสร้าง Q-Tree:
# ที่มา: src/config.py
if global_task == 'train' and 'nl2sva' in task:
# Training builds suggestions / Q-Trees; retrieval is disabled here.
use_RAG = False
use_JG = False
RAG_content = ['Suggestions']
# Number of self-improvement iterations per training sample.
num_iter = 25
train_temp_setting = "random"
if train_temp_setting == "random":
change_only_bleu_same = True
low_temp = 0
high_temp = 1.0
use_QTree = True
if use_QTree:
# Number of questions expanded per Q-Tree level.
question_tree_width = 3
PEC_method = 'JasperGold'
ในระหว่างการอนุมาน ระบบจะเปิดใช้งานโมดูล RAG และเปิดใช้กลไก Q-Tree enhanced retrieval:
# ที่มา: src/config.py
elif global_task == 'inference' and 'nl2sva' in task:
use_RAG = True
similarity_str = ["Question"]
eval_content = ["similarity","jg"]
if use_RAG:
RAG_content = ['Examples', 'Suggestions']
if 'Examples' in RAG_content:
prompting_instruction = 0
Examples_top_k = 1
if 'Suggestions' in RAG_content:
Suggestions_top_k = 3
Suggestions_Reasoning = False
# Enable FVRuleLearner's Q-Tree-enhanced retrieval.
retrieval_on_ranking = True
if retrieval_on_ranking:
qtree_similarity_top_k = 5
qtree_ranking_mode = 'prompt'
rule_source = 'generate'
llm_score_weight = 0.5
operator_score_weight = 0.5
operator_pruning_threshold = 0.0
deduplication = True
operator_explanation = False
filter_functionality = True
retrieve_str = ["Suggestions"]
load_suggestions_path = DEFAULT_TRAIN_LOGDIR
แผนการกำหนดค่านี้ควรค่าแก่การอภิปรายในเชิงลึก โดยแยกความแตกต่างระหว่าง “การค้นหาตัวอย่าง” และ “การค้นหากฎ” อย่างชัดเจน
- Examples เป็นกลไกการเรียนรู้ในบริบท (in-context learning) แบบคลาสสิก
- Suggestions คือความรู้กฎที่กลั่นกรองจากกระบวนการแก้ไขข้อผิดพลาดในประวัติศาสตร์
เห็นได้ชัดว่าสิ่งหลังคือแกนหลักทางเทคนิคที่แท้จริงของ FVRuleLearner
สี่. Q-Tree: แยกข้อผิดพลาดครั้งเดียวเป็นเส้นทางการอนุมานที่เรียนรู้ได้
4.1 ทำไมต้องเป็นโครงสร้างต้นไม้ ไม่ใช่แค่ข้อความสะท้อน
ระบบซ่อมแซมตัวเองของ LLM ส่วนใหญ่เมื่อพบกับความล้มเหลว จะถามเพียงว่า: “โปรดอธิบายข้อผิดพลาดและให้คำแนะนำ” ในขณะที่ FVRuleLearner เลือกเส้นทางที่มีโครงสร้างมากกว่า: Q-Tree โดยแยกความแตกต่างระหว่าง assertion ที่สร้างขึ้นกับ assertion อ้างอิง ออกเป็นคำถามหลายระดับ:
- ความรู้พื้นฐาน: ครอบคลุมคำอธิบายภาษาธรรมชาติ, testbench, assertion ที่สร้างขึ้น, assertion อ้างอิง และความรู้ทั่วไปเกี่ยวกับไวยากรณ์ SVA
- คำถามเชิงสำรวจ: ตั้งคำถามจากหลายมิติ เช่น ตัวดำเนินการ (operator), จังหวะเวลา (timing), การเปรียบเทียบ (comparison)
- คำถามวิเคราะห์เฉพาะ: สอบถามเชิงลึกสำหรับแต่ละจุดที่แตกต่าง
- การสร้างกฎ: บีบอัดผลการวิเคราะห์เป็นกฎที่สามารถนำกลับมาใช้ใหม่ได้
โครงสร้างข้อมูลหลักถูกกำหนดไว้ใน src/qtree_builder.py:
# ที่มา: src/qtree_builder.py
class QuestionLevel(Enum):
"""Levels in the Q-Tree hierarchy"""
BACKGROUND = "background"
EXPLORATORY = "exploratory"
SPECIFIC_ANALYSIS = "specific_analysis"
RULE_GENERATION = "rule_generation"
@dataclass
class QuestionNode:
"""Node in the Q-Tree structure"""
id: str
question: str
level: QuestionLevel
parent_id: Optional[str] = None
children: List[str] = field(default_factory=list)
answer: Optional[str] = None
rules_generated: List[str] = field(default_factory=list)
metrics: Dict[str, Any] = field(default_factory=dict)
class QTreeBuilder:
"""Builds Q-Tree for assertion analysis and rule generation"""
def __init__(self, agents: Dict[str, Any], config_flags=None):
self.agents = agents
self.nodes: Dict[str, QuestionNode] = {}
self.tree_results = []
self.max_questions_per_level = getattr(config_flags, 'question_tree_width', 3) if config_flags else 3
self._last_diversity_metrics = None
self._row_data = None
self.qa_time = 0.0
สามารถเปรียบเทียบได้กับกระบวนการตรวจสอบโค้ดของผู้เชี่ยวชาญด้านการตรวจสอบเชิงรูปแบบ: ผู้เชี่ยวชาญจะไม่เพียงแค่พูดว่า “ผิด” แต่จะถามว่า “การนัยเชิงเวลาถูกต้องหรือไม่?” “ตัวดำเนินการเปรียบเทียบตรงกับตรรกะสี่สถานะหรือไม่?” “ควรวางเงื่อนไขไว้ใน antecedent หรือ consequent?” — คำถามเหล่านี้ก่อตัวเป็นโครงสร้างต้นไม้ และในที่สุดจะตกตะกอนเป็นกฎที่สามารถนำกลับมาใช้ใหม่ได้
4.2 กระบวนการสร้าง Q-Tree
# ที่มา: src/qtree_builder.py
def build_qtree_for_assertion_pair(self,
generated_assertion: str,
reference_assertion: str,
row: Any,
metrics: Dict[str, Any]) -> List[QuestionNode]:
"""
Build a Q-Tree to analyze differences between generated and reference assertions
Tree Structure:
Root: Background Knowledge (context about the problem)
Level 1: Exploratory questions about major differences
Level 2: Specific analysis questions for each difference
Level 3: Rule generation based on the analysis
"""
tree_nodes = []
node_counter = 0
self._row_data = row
background_knowledge = self._get_background_knowledge(row, generated_assertion, reference_assertion)
exploratory_questions = self._generate_exploratory_questions(
generated_assertion, reference_assertion, metrics, row
)
for question in exploratory_questions:
node = QuestionNode(
id=f"explore_{node_counter}",
question=question,
level=QuestionLevel.EXPLORATORY,
parent_id=None,
metrics=metrics
)
node.answer = self._answer_exploratory_question(
question, generated_assertion, reference_assertion, row
)
# Level 2: Generate specific analysis questions
for parent_node in exploratory_nodes:
specific_questions = self._generate_specific_analysis_questions(
parent_node, generated_assertion, reference_assertion
)
# Level 3: Generate rules based on analysis
for parent_node in specific_nodes:
rules = self._generate_rules_from_analysis(
parent_node, generated_assertion, reference_assertion
)
แนวคิดการออกแบบของโค้ดนี้ชัดเจนมาก: Q-Tree ไม่ได้ถูกใช้โดยตรงสำหรับ “การแก้ไขโค้ด” แต่ก่อนอื่นจะจัดโครงสร้างพื้นที่ข้อผิดพลาดอย่างเป็นระบบ สำหรับภาษา SVA ซึ่งพึ่งพาความหมายของตัวดำเนินการอย่างมาก กลไกการสอบถามเชิงโครงสร้างมีความเสถียรและเชื่อถือได้มากกว่าการสะท้อนครั้งเดียว ตัวอย่างเช่น:
|->และ|=>แสดงถึงความสัมพันธ์ “การนัย” แบบเดียวกันหรือไม่? คำตอบคือไม่ — อันแรกคือการนัยที่ทับซ้อนกันภายในรอบเดียวกัน ส่วนอันหลังคือการนัยที่ไม่ทับซ้อนซึ่งจะเริ่มในรอบถัดไป==และ===เป็นเพียงความแตกต่างของรูปแบบการเขียนโค้ดหรือไม่? ไม่ใช่ อย่างหลังทำการเปรียบเทียบสี่สถานะ (case equality)&&และ||สามารถเลือกได้โดยสัญชาตญาณทางภาษาเท่านั้นหรือไม่? ไม่ได้ การเลือกนี้กำหนดโดยตรงว่าขอบเขตของเงื่อนไข antecedent กว้างหรือแคบเกินไป
คุณค่าหลักของ Q-Tree คือการแปลงความแตกต่างข้างต้นเป็น “โหนดคำถามที่อธิบายได้” จากนั้นบีบอัดโหนดเหล่านี้เป็นกฎ (rule) ที่สามารถค้นหาได้ในภายหลัง
ห้า. RAG และการค้นหาเสริม: ไม่ใช่การหาคำตอบที่คล้ายกัน แต่เป็นการหาประสบการณ์การแก้ไขข้อผิดพลาดที่คล้ายกัน
5.1 RAGAgent จัดระเบียบเอกสารอย่างไร
RAGAgent ใน FVRuleLearner รองรับโหมดการค้นหาสองประเภท: Examples และ Suggestions โหมด Examples มีเป้าหมายเพื่อค้นหาตัวอย่างคำถามและคำตอบที่คล้ายกัน ในขณะที่โหมด Suggestions ใช้สำหรับค้นหากฎในประวัติศาสตร์ ในระหว่างการเริ่มต้น ระบบจะเลือกโมเดล embedding โดยอัตโนมัติ โดยการกำหนดค่าเริ่มต้นคือ all-MiniLM-L6-v2
# ที่มา: src/rag_agent.py
class RAGAgent:
def __init__(self, documents, rag_type, embedding_model='sbert'):
self.delimiter = "<---->"
self.rag_type = rag_type
self.qtree_engine = None
if rag_type == "Suggestions":
if FLAGS.filter_functionality:
documents = [doc for doc in documents if self.check_functionality(doc)]
print(f"@@@DEBUG: Length of the filtered documents is @@@ {len(documents)} @@@")
self.original_documents = [doc.replace(self.delimiter, "n").strip() for doc in documents]
self.documents = [self.extract_section(doc, FLAGS.similarity_str, full_string=True) for doc in documents]
if rag_type == "Suggestions":
self.retrieve_documents = [self.extract_section(doc, FLAGS.retrieve_str, full_string=True) for doc in documents]
elif rag_type == "Examples":
self.retrieve_documents = [self.extract_section(doc, ["all"], full_string=True) for doc in documents]
self.model = self._load_model(embedding_model)
self
⚠️ หมายเหตุ: เนื้อหาได้รับการแปลโดย AI และตรวจสอบโดยมนุษย์ หากมีข้อผิดพลาดโปรดแจ้ง
☕ สนับสนุนค่ากาแฟทีมงาน
หากคุณชอบบทความนี้ สามารถสนับสนุนเราได้ผ่าน PromptPay
SCAN TO PAY WITH ANY BANK
本文来自网络搜集,不代表คลื่นสร้างอนาคต立场,如有侵权,联系删除。转载请注明出处:https://www.itsolotime.com/th/archives/33488
