- SymbolicAI เป็น เฟรมเวิร์กเชิงประสาท-สัญลักษณ์ ที่ผสาน การเขียนโปรแกรม Python แบบดั้งเดิม เข้ากับธรรมชาติที่แยกเชิงอนุพันธ์ได้และตั้งโปรแกรมได้ของ LLM โดยมีเป้าหมายให้ใช้งานได้อย่างเป็นธรรมชาติภายใน Python
- แนวคิดหลักคือ primitive ที่อิงกับอ็อบเจ็กต์
Symbol และ contracts สำหรับตรวจสอบและแก้ไขผลลัพธ์ของ LLM โดยพฤติกรรมเริ่มต้นจะเริ่มในโหมดเชิงไวยากรณ์เพื่อความปลอดภัยและความเร็ว
Symbol ทำงานเหมือนค่า Python ปกติในโหมดเชิงไวยากรณ์ และจัดการบริบทกับความหมายในโหมดเชิงความหมาย โดยสามารถสลับผ่าน semantic=True, .sem, และการเรียกฟังก์ชันเชิงความหมายอย่าง .map()
- ระบบสัญญานำหลักการ Design by Contract มาประยุกต์กับเวิร์กโฟลว์ LLM เพื่อจัดการการตรวจสอบอินพุต การเปลี่ยนสถานะ การสร้างโดย LLM การตรวจสอบเอาต์พุต และคำตอบสำรองเมื่อเกิดความล้มเหลว ภายในโฟลว์เดียวที่อิงกับเดคอเรเตอร์
- เริ่มติดตั้งได้ด้วย
pip install symbolicai และในการใช้งานจริงจำเป็นต้องตั้งค่า symconfig กับ symai.config.json โดยเอนจินเชิงประสาท-สัญลักษณ์เป็นสิ่งจำเป็นสำหรับการใช้แพ็กเกจ symai
โมเดลที่ SymbolicAI มุ่งไปสู่
- SymbolicAI เป็นเฟรมเวิร์ก neuro-symbolic ที่รองรับทั้งโค้ด Python ทั่วไปและการประมวลผลเชิงความหมายที่อิงกับ LLM
- ด้วยการออกแบบแบบโมดูลาร์ จึงสามารถขยายและปรับแต่งให้เหมาะกับความต้องการได้
- รองรับการเขียนเอนจินเอง การโฮสต์เอนจินในเครื่อง การค้นหาเว็บ และการเชื่อมต่อเครื่องมืออย่างการสร้างภาพ
- ชื่อโปรเจ็กต์ตั้งขึ้นเพื่อให้เครดิตกับงานบุกเบิกพื้นฐานของ Allen Newell และ Herbert Simon
primitive Symbol
- หัวใจของ SymbolicAI คืออ็อบเจ็กต์
Symbol ซึ่งสามารถใช้โอเปอเรชันขนาดเล็กที่ประกอบเข้าด้วยกันได้ด้วยไวยากรณ์แบบ native ของ Python
Symbol มีโหมดการทำงาน 2 แบบ
- Syntactic: ทำงานเหมือนค่า Python ปกติ เช่น สตริง ลิสต์ หรือจำนวนเต็มที่ส่งเข้าไป
- Semantic: เชื่อมต่อกับเอนจินเชิงประสาท-สัญลักษณ์เพื่อจัดการความหมายและบริบท
- ค่าเริ่มต้นคือ โหมดเชิงไวยากรณ์
- โอเปอเรเตอร์ของ Python อย่าง
==, ~, & ถูก overload ไว้ใน symai
- หากเรียกเอนจินทันทีทุกครั้งที่มีการเปรียบเทียบหรือ bitshift จะทำให้ช้าและอาจเกิดผลข้างเคียงที่ไม่คาดคิด
- การเปิดพฤติกรรมเชิงความหมายเฉพาะในจุดที่จำเป็นช่วยรักษาทั้งความปลอดภัยและความเร็ว
วิธีสลับไปยังโหมดเชิงความหมาย
- หากระบุ
semantic=True ตอนสร้าง อ็อบเจ็กต์จะทำงานเป็น Symbol เชิงความหมาย ตั้งแต่ต้น
- ในตัวอย่าง
Symbol("Cats are adorable", semantic=True) จะทำให้ "feline" in S ถูกประเมินเป็น True
- เมื่อจำเป็น สามารถใช้การโปรเจกต์
.sem เพื่อสลับเป็นพฤติกรรมเชิงความหมาย และกลับสู่พฤติกรรมเชิงไวยากรณ์ด้วย .syn
- แม้จะมีค่าเดียวกันคือ
"Cats are adorable" แต่ใน S.sem นั้น "feline" in S.sem เป็น True ขณะที่ใน S แบบปกติเป็น False
- โอเปอเรชันแบบ dot notation อย่าง
.map() หรือการเรียกฟังก์ชันเชิงความหมายอื่น ๆ จะสลับ Symbol ไปสู่โหมดเชิงความหมายโดยอัตโนมัติ
- ในตัวอย่าง เมื่อใช้
convert all fruits to vegetables กับรายการผลไม้ จะเปลี่ยนเฉพาะผลไม้เป็นผัก และคง cat, dog ไว้เหมือนเดิม
- การโปรเจกต์
.sem และ .syn เป็นการวางชั้นพฤติกรรมที่ต่างกันลงบนอ็อบเจ็กต์พื้นฐานเดียวกัน จึงสามารถเชื่อมการทำงานเชิงไวยากรณ์และเชิงความหมายต่อเนื่องกันบน Symbol เดียวได้
ตัวอย่างโอเปอเรชันที่มีให้
- SymbolicAI รองรับ primitive หลากหลายแบบ และเอกสารอยู่ที่ primitives
== ในโหมดเชิงไวยากรณ์จะตรวจสอบการตรงกันแบบ literal ส่วนในโหมดเชิงความหมายจะจัดการความเท่ากันแบบฟัซซีหรือเชิงแนวคิด เช่น "Hi" กับ "Hello"
+ ในโหมดเชิงไวยากรณ์คือการบวกตัวเลข/สตริง/ลิสต์ ส่วนในโหมดเชิงความหมายคือการรวมที่มีความหมาย การผสม หรือการผสานแนวคิด
& ในโหมดเชิงไวยากรณ์คือ bit/logical AND ส่วนในโหมดเชิงความหมายใช้กับการเชื่อมตรรกะ การอนุมาน และการรวมบริบท
- ความสามารถเฉพาะฝั่งเชิงความหมายมี เช่น
.choice(cases, default), .foreach(condition, apply), .cluster(**clustering_kwargs?), .similarity(other, metric?, normalize?)
.cluster() ใช้จัดกลุ่มข้อมูลเชิงความหมาย โดยอาศัย DBSCAN ของ sklearn
.similarity() ใช้คำนวณความคล้ายกันระหว่าง embeddings
วิธีจัดการเอาต์พุต LLM ด้วยสัญญา
- SymbolicAI นำหลัก Design by Contract มาปรับใช้กับโลกของ LLM จากแนวคิดที่ว่า LLM อาจหลอนได้ แต่โค้ดไม่ควรเป็นเช่นนั้น
- สัญญาไม่ได้พึ่งพาเพียงการทดสอบหลังบ้าน แต่ผูก data model และข้อกำหนดการตรวจสอบเข้ากับเดคอเรเตอร์ เพื่อจัดการความถูกต้องตั้งแต่ขั้นออกแบบ
- เดคอเรเตอร์สัญญาในโค้ดตัวอย่างใช้ตัวเลือกดังนี้
pre_remedy=True: พยายามแก้ไขอินพุตที่ไม่ถูกต้องโดยอัตโนมัติ
post_remedy=True: พยายามแก้ไขเอาต์พุต LLM ที่ไม่ถูกต้องโดยอัตโนมัติ
accumulate_errors=True: ส่งต่อประวัติข้อผิดพลาดในแต่ละครั้งที่ retry
verbose=True: แสดงความคืบหน้าในเทอร์มินัล
remedy_retry_params: ใช้ tries=3, delay=0.4, max_delay=4.0, jitter=0.15, backoff=1.8, graceful=False
- โฟลว์ระดับสูงของคลาส
Expression ที่ใช้สัญญามีดังนี้
prompt: คำอธิบายแบบคงที่ที่นิยามสิ่งที่ LLM ต้องทำ และเป็นสิ่งจำเป็น
pre: ตรวจสอบอินพุต เป็นตัวเลือก
act: เปลี่ยนสถานะ เป็นตัวเลือก
- LLM: เอนจินของ SymbolicAI จะสร้างคำตอบที่คาดหวัง
post: ตรวจสอบว่าคำตอบตรงตามกฎเชิงความหมายหรือไม่ เป็นตัวเลือก
forward: จำเป็นเสมอ และเมื่อสัญญาสำเร็จจะคืนค่าอ็อบเจ็กต์ LLM ที่ผ่านการตรวจชนิดแล้ว หรือคืนคำตอบ fallback แบบ graceful เมื่อไม่สำเร็จ
- เอกสารของสัญญาอยู่ที่ DeepWiki's contract validation system และ features/contracts
การติดตั้งและความสามารถเสริม
- การติดตั้งพื้นฐานทำผ่าน pip
pip install symbolicai
- สามารถ clone รีโพซิทอรีและตั้งค่า Python virtual environment ด้วย uv
>= 0.9.17 ได้เช่นกัน
git clone git@github.com:ExtensityAI/symbolicai.git
cd symbolicai
uv sync --python x.xx
source ./.venv/bin/activate
- SymbolicAI ใช้หลายเอนจินในการประมวลผลข้อความ เสียง และภาพ รวมถึงการเข้าถึง search engine สำหรับค้นหาข้อมูลบนเว็บ
- dependency แบบเลือกติดตั้งสามารถเพิ่มเป็น extra ตามฟีเจอร์ได้
bitsandbytes, hf, lean, llama_cpp, ocr, qdrant, scrape, search, serpapi, services, solver, whisper, wolframalpha
- สามารถติดตั้ง dependency เสริมทั้งหมดได้ในครั้งเดียว
pip install "symbolicai[all]"
uv sync --frozen จะติดตั้ง dependency ตาม lock file ที่ให้มาแบบตรึงเวอร์ชัน
- dependency เสริมบางตัวอาจต้องมีขั้นตอนติดตั้งเพิ่มเติม และบางตัวปัจจุบันรองรับในเชิงทดลองเท่านั้น จึงอาจทำงานไม่เป็นไปตามคาด
การจัดการคอนฟิกและเอนจินที่จำเป็น
- SymbolicAI ใช้ ระบบจัดการคอนฟิก แบบอิงลำดับความสำคัญ
- คอนฟิกจะถูกโหลดจาก 3 ตำแหน่งตามลำดับความสำคัญ
- โหมดดีบักในไดเรกทอรีทำงานปัจจุบัน: มีความสำคัญสูงสุด และใช้กับ
symai.config.json เท่านั้น
- คอนฟิกตามสภาพแวดล้อมของ Python: อยู่ที่
{python_env}/.symai/ และเหมาะกับคอนฟิกต่อโปรเจ็กต์
- คอนฟิกแบบ global ในโฮมไดเรกทอรี: อยู่ที่
~/.symai/ และทำหน้าที่เป็น fallback พื้นฐาน
- ไฟล์คอนฟิกที่อยู่ภายใต้การจัดการมี 3 ไฟล์
symai.config.json: คอนฟิกหลักของ SymbolicAI
symsh.config.json: คอนฟิกของเชลล์
symserver.config.json: คอนฟิกของเซิร์ฟเวอร์
symconfig จะแสดงตำแหน่งคอนฟิก พาธของคอนฟิกที่ใช้งานอยู่ และคอนฟิกปัจจุบันแบบซ่อนข้อมูลสำคัญ พร้อมเริ่มแคชแพ็กเกจเริ่มต้นและการตั้งต้นไฟล์คอนฟิก
- หากต้องการใช้แพ็กเกจ
symai จำเป็นต้องมี เอนจินเชิงประสาท-สัญลักษณ์
- การกำหนดพร็อพเพอร์ตีเอนจินใน
symai.config.json ของพาธโปรเจ็กต์ สามารถใช้แทน environment variables ได้
- ตัวอย่างคอนฟิกประกอบด้วยค่า
NEUROSYMBOLIC_ENGINE_MODEL เป็น claude-sonnet-4-6, โมเดล embedding เป็น text-embedding-3-small, โมเดล TTS เป็น tts-1, โมเดล OCR เป็น mistral-ocr-latest, และเอนจินสำหรับ indexing เป็น qdrant
- โดยค่าเริ่มต้น การเตือนสำหรับผู้ใช้จะเปิดอยู่ และสามารถปิดได้ด้วย environment variable
SYMAI_WARNINGS=0
การทดสอบ เอกสาร และไลเซนส์
- ตัวอย่างการรันการทดสอบมีดังนี้
pytest tests
pytest -m mandatory
pytest --cov=symbolicai tests
- ก่อนทดสอบ ต้องตั้งค่าคอนฟิกให้ถูกต้องก่อน
- ขั้นตอนถัดไปสามารถดูได้จาก SymbolicAI DeepWiki page, paper, และ video tutorials
- ข้อมูลการอ้างอิงชี้ไปยัง arXiv preprint ปี 2024 ชื่อ
Symbolicai: A framework for logic-based approaches combining generative models and solvers
- ไลเซนส์ของโปรเจ็กต์คือ BSD-3-Clause License
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
ฟีเจอร์ที่เหมือนมนตร์วูดู แบบนี้น่าสนใจที่สุด
เช่น ถ้าใช้
mapเชิงความหมายกับ['apple', 'banana', 'cherry', 'cat', 'dog']แล้วสั่งว่า “เปลี่ยนผลไม้ทั้งหมดเป็นผัก” ก็จะได้ผลประมาณ['carrot', 'broccoli', 'spinach', 'cat', 'dog']และequals()จะให้ผลการเปรียบเทียบต่างกันตามบริบท เช่นcontext='greeting context'หรือcontext='politeness level'ตัวดำเนินการระดับบิตก็ถูกใช้เหมือนการเชื่อมตรรกะเชิงความหมาย เช่น
horn_rule & observationนำไปสู่การอนุมาน ทำให้interpret()ดูทรงพลังอยากรู้แรงบันดาลใจในการสร้าง, การนำไปใช้จริง, และเคสการใช้งานที่ชอบที่สุดจนถึงตอนนี้
แกนหลักคือการทำ ตัวดำเนินการเชิงสัมพันธ์ เวอร์ชันเชิงความหมายในรูปส่วนขยายของไลบรารี dataframe บน Python และการเรียกแต่ละครั้งจะกลายเป็นจุด “โมเดล” สำหรับงานที่ซับซ้อนขึ้นในภายหลัง เช่น แนวทางแบบอิงการเรียนรู้
ฝั่งคลาวด์ SQL อย่าง Snowflake ก็ดูเหมือนกำลังไปทางนี้ และที่ louie.ai ก็ใช้แนวทางคล้ายกัน คือเมื่อคุยกับข้อมูลอย่าง Splunk, Databricks, graph DB ผ่าน AI notebook/dashboard/API (เช่น MCP) ระบบจะหา operator เชิงสัญลักษณ์+เชิงความหมายที่เหมาะกับบริบท ซึ่งใช้จริงแล้วค่อนข้างมีประโยชน์
เคสหลัก 80% คือการสร้าง dataframe ที่เสริมด้วย map เชิงความหมาย เช่น “ดึงการแจ้งเตือนทั้งหมดจาก Splunk index xyz แล้วเพิ่มคอลัมน์ที่ทำเครื่องหมายรายการน่าสงสัยกับคอลัมน์ที่อธิบายเหตุผล” จากนั้นตามด้วย reduce เชิงความหมาย เช่น “สรุปสิ่งที่พบ” เพื่อให้ได้คำอธิบายเป็นภาษาธรรมชาติ
ตั้งแต่เริ่มโปรเจกต์ปลายปี 2022 ก็ไม่ได้มีอะไรเปลี่ยนไปมากนัก แค่โมเดลดีขึ้นเท่านั้น ตัวดำเนินการดิบจำนวนมากมีมาตั้งแต่ยุค GPT-3 แล้ว
สิ่งที่สำคัญกว่าช่วงหลังคือ การสนับสนุน DbC ซึ่งจุดที่พิเศษคือสามารถเชื่อม contract เข้าด้วยกันได้ และ guardrail ถูกส่งต่อได้ดี จนแก้ปัญหาแทบทุกอย่างที่โยนใส่ในบริบทของ agent ได้
Perplexity มีประโยชน์น้อยลงเพราะ OpenAI web search และ OpenAI web search เองก็ยังไม่พอเท่ากับการปรับแต่งเอง จึงสร้าง agent สำหรับ deep research ขึ้นมาเอง: https://x.com/futurisold/status/1931751644233945216
ที่บริษัทก็เชื่อม contract 3 ตัวเพื่อทำ การสร้างเอกสารแบบ end-to-end และมีตัวอย่างผลลัพธ์อยู่ที่นี่: https://drive.google.com/file/d/1Va7ALq_N-fTYeumKhH4jSxsTrWD...
อินพุตคือคำขอให้เปรียบเทียบและวิเคราะห์ system prompt ของผู้ให้บริการ AI รายหลัก ๆ เพื่อค้นหารูปแบบอย่าง XML/Markdown/JSON, คำสั่งที่ประจบเอาใจหรือชี้นำให้ถูกจัดการ, ข้อจำกัดการใช้เครื่องมือ, guardrail ด้านจริยธรรม, และความแตกต่างในการออกแบบ alignment แล้วสังเคราะห์เป็นรายงานทางเทคนิค ส่วนคำสั่งที่สร้างขึ้นถูกขยายเป็นคำถามเฉพาะเจาะจงที่เปรียบเทียบโครงสร้าง system prompt, กรอบทางภาษา, และข้อจำกัดเชิงปฏิบัติการของ OpenAI, Google, Anthropic, xAI ฯลฯ
contract ถูกแนะนำไว้ในบทความเดือนมีนาคม และแม้หลังจากนั้นจะพัฒนาไปมาก แต่พื้นฐานและแรงจูงใจยังเหมือนเดิม: https://futurisold.github.io/2025-03-01-dbc/
น่าจะช่วยให้เข้าใจได้ดีขึ้นถ้าลิงก์ paper กับ notebook ตัวอย่างมาด้วย
https://github.com/ExtensityAI/symbolicai/blob/main/examples...
https://arxiv.org/pdf/2402.00854
เจ๋งดี
ถ้าใช้ operator อย่าง
==,+เป็น operator เชิงความหมาย ไม่ใช่แค่ไวยากรณ์ได้ ก็น่าจะเป็นปุ๋ยให้ไอเดียใหม่ ๆ และให้ความรู้สึกคล้ายตอน word embedding เพิ่งออกมา แล้วเกิดพีชคณิตเชิงแนวคิดแบบหลวม ๆ อย่าง “King - Man + Woman = Queen”แต่การผสาน neural+symbolic ตรงนี้ดูค่อนข้างตื้นและมีกำแพงกั้น เหมือนระบบส่วนใหญ่ โดยในการจัดประเภทน่าจะใกล้กับ Type 3 / Neuro;Symbolic: https://harshakokel.com/posts/neurosymbolic-systems
เวทมนตร์จริง ๆ น่าจะเกิดเมื่อไปสู่การผสานที่ลึกกว่าระดับพื้นฐาน และที่บริษัทเรา (https://onton.com) ก็กำลังคิดถึง ระบบหลังยุค LLM ที่มี representation แบบรวมซึ่งไม่ใช่ทั้ง symbolic ล้วน ๆ และไม่ใช่เมทริกซ์ float หนาแน่น, เรียนรู้แบบค่อยเป็นค่อยไปจากข้อมูลน้อยและมี noise โดยหลีกเลี่ยง catastrophic forgetting, มีความน่าเชื่อถือแน่นอนสำหรับคณิตศาสตร์และการดำเนินการเชิงสัญลักษณ์, และไม่มี hallucination
การเอาระบบเดิม ๆ มาต่อกันเหมือนใช้ปืนกาวก็มีประโยชน์ แต่สถาปัตยกรรมแบบบูรณาการน่าจะเปลี่ยนทุกอย่าง
ส่วน contract ด้านความถูกต้องมีบั๊กอยู่
หลัง
valid_opts = ['A', 'B', 'C']มีif v not in valid_sizes:แต่ valid_sizes ไม่ได้ถูกนิยามไว้“Symbolic AI” เป็นคำที่มีนิยามชัดเจนอยู่แล้ว เลยแอบเสียดายนิดหน่อย: https://en.m.wikipedia.org/wiki/Symbolic_artificial_intellig...
อาจเปลี่ยนชื่อก็ได้ และใน paper มีเชิงอรรถเกี่ยวกับการเลือกชื่อนี้
ตั้งใจจะให้เครดิตกับงานพื้นฐานของ Newell และ Simon ที่เป็นแรงบันดาลใจให้โปรเจกต์นี้
อยากรู้โครงสร้างต้นทุน
อยากรู้ว่าทุกครั้งที่รันบรรทัดที่มีการคำนวณด้วยภาษาธรรมชาติ จะต้องจ่ายค่า inference ของ LLM หรือไม่ และถ้าใช้ API ภายนอกจะถูกคิดเงินทุกครั้งจริง ๆ หรือเปล่า
เช่น ถ้าเรียกฟังก์ชัน “symbolic” ภายในลูปจะเกิดอะไรขึ้น
เช่น ถ้าใช้ OpenAI การดำเนินการ เชิงความหมาย ทั้งหมดจะกลายเป็นการเรียก OpenAI API
ถ้าโฮสต์ LLM แบบโลคัลด้วย
llama.cppก็จะไม่มีค่า inference นอกเหนือจากต้นทุนการโฮสต์โมเดลทุกวันนี้โค้ดถูกสร้างโดย LLM อยู่แล้ว จึงสงสัยว่าโครงสร้างไวยากรณ์เฉพาะอย่าง
Symbolที่เก็บบริบทและจัดการได้ด้วยตัวดำเนินการของ Python ช่วยอะไรได้มากกว่าโค้ด Python ทั่วไปที่มนุษย์สั่งให้มีเงื่อนไขตรวจสอบและถ่วงดุลอย่างไรเช่น แทนที่จะใช้ไวยากรณ์สำหรับเปลี่ยนผลไม้เป็นผัก ก็อาจ prompt ให้ LLM สร้างโปรแกรมที่รับรายการผลไม้ แล้วเรียก LLM ภายในเพื่อคืนค่าผักที่สอดคล้องกันได้
อยากเข้าใจความแตกต่าง
ถ้าให้ LLM สร้างระบบเชิงรูปแบบ จะตรวจสอบได้ง่ายกว่าโปรแกรมเอนกประสงค์มาก
สงสัยว่าเคยพิจารณา neural-symbolic AI ที่วิวัฒนาการได้ด้วยหรือไม่
https://deepwiki.com/dubprime/mythral/3.2-genome-system
หรือถ้าเป็นฝั่งที่รู้สึกถึงอารมณ์ล่ะ?
https://deepwiki.com/search/how-do-emotives-work_193cb616-54...
สงสัยด้วยว่าเคยอ่าน Society of Mind ของ Marvin Minsky หรือไม่
เคยทดลองตั้งแต่ theory of mind ไปจนถึงอารมณ์ด้วย แต่ตอนนี้รู้สึกว่าโมเดลยังไม่ถึงระดับนั้นพอ ทำให้ผลตอบแทนต่อความพยายามลดลง เลยหยุดไว้
จะรื้อกลับมาทำใหม่ได้ง่าย แต่ Minsky ไม่ใช่คนโปรด และในรุ่นนั้นผมถูกใจฝั่ง Newell/Simon มากกว่า
เคยลองเล่น symbolic regression นิดหน่อย โดยให้ LLM ตรวจเอกสารแล้วสร้าง primitive operators หรือก็คือตัวดำเนินการที่จะใส่เข้าไปใน PySR ของ GitHub (github.com/MilesCranmer/PySR)
ไปได้ไม่ไกลเพราะการเชื่อมทุกอย่างเข้าด้วยกันทำได้ยาก แต่ถ้ามีเครื่องมือแบบนี้ก็อาจลองใหม่ได้
แนะนำให้ใช้ contracts
เคยใช้แนวทางคล้ายกันกับ contracts ที่ค่อย ๆ “ต่อ” กราฟ ontology ที่แตกทีละรอบ
มีโครงสร้างอย่าง
Merge,Bridge,Prune,Operationเป็น data model ที่ช่วยให้เกิดไอเดีย โดยแต่ละตัวกำหนดดัชนีคลัสเตอร์ที่จะ merge ความสัมพันธ์คลาสแม่-ลูก และรายการคลาสที่จะ prune จากนั้นใช้ validator บังคับเงื่อนไขของการดำเนินการแบบ binary/unaryในทำนองเดียวกัน สามารถสร้างโมเดลสำหรับ operators แล้วให้ contract แก้ทีละ operator จากนั้นจึงนำ operator นั้นไปใช้ได้