Галоўная / Артыкулы / SHACL TDD для агентаў GraphRAG: Адна правіла кантролю, яка зупіняе небяспечныя дзеяння

SHACL TDD для агентаў GraphRAG: Адна правіла кантролю, яка зупіняе небяспечныя дзеяння

Кодавайце політику з максымальным рызыкам 30% для адзынавання керуючыхяктароў у формате SHACL, падтвердзіце яе за дапамою pytest, і старайцеся пабачыць, як брандмауэр онтологіі зупініць агента пад час дэманстрацыі контракту на суму 2,3 мільйона долераў.

1411 слоў

Чытанне нотатак пра архітектуру не ўзмаўляецца з выкананнем правіла керавання. У этай статыце, якая ўзьмліваеся пасля трывайшага порэвання — звычайнага RAG, GraphRAG і GraphRAG, адгуканага да OWL/SHACL/policy — на прыкладзе даговора за $2,3 млн, акцэнт ставіцца на пераносныя навыкі: закодаваць аднае бізнес-правіло у вобраз, падтвердзіць яго за дапамогою автаматызаванай перацэнкі і спакульгаваць, як агент адмовіцца прыняць рашэнне.

У репазітарые Ontology RAG Firewall знаходзяцца слоўнік cont:, файлы вобразаў і офлайн-дэманстрацыя, якія викорыстаны тут. Клонаваце яго, пераканайцеся, што весь комплект працуе нормальна на рэпозітарые main, а потым, за жаданнем, запускайце старэйшы коміт, каб лячна пазнакаць цикл «чырвоны-зелены».

Пераканайцеся, што базовы стан на main

git clone https://github.com/cloudbadal007/ontology-rag-firewall
cd ontology-rag-firewall
pip install -e ".[dev]"
pytest -q                    # 18 passed (full suite)
python examples/demo_offline.py

Фіксацыя на версіі 6318929 є необавязковай, якщо важна пасляпэўнай перакананая падказка статыцы; падказка з рэпозітарые main можа вже быць новейшай.

Здаровы рэзультат паказвае 18 прынятыя. У дэмаверсіі без падзейчання з’яўляецца апавешчэнне, спрытнае да керуючых апошніх рашэнняў, у раздзеле пра аблегчэнне наследкав, падобнае гэтаму:

Safe to act: 🚫 NO
- Flagged: 5
...
⚠️ EXECUTIVE APPROVAL: Liability cap is below 30% of contract value. Cap ratio: 25.00%. Agent action requires executive sign-off.
...
AGENT ACTION: HALTED. Routed to human review queue.
Total value protected: $2,300,000

Гэтае апавешчэнне – гэта самае, што было уведзена ў новай версіі. Рэштка тексту апісвае, як гэта было реалізавана за дапамогою падходу разработкі, спачатку тэставання.

Політыка, якая кодуецца

Адзіннаццаць форматаў вузлаў уже ўключаныя ў contract_domain_shacl.ttl і абходзяць такія аспекты, як умовы платежаў, тэрміны паведамлення, стандарты пра час выконання, выкарыстоўванне данных з низкім рэвераментам, прычыны неадекватных заходаў, аўтоперазнавленне, відсутнасць тэкста пра аблегчэнне наследкав, перагляд прымітных збиткаў, ступенек 10% ад вялічыны, кейсы з вялікай вялічынай, але низкім абсалютным лімітом, а таксама ступенек для керуючых, які падкрэсляецца ў гэтым кароткам узорку.

У дэмаверсійнай угодзе максімацыя 575 тысяч долераў станавіць 25% ад 2,3 мільйона долераў — гэта больш, чым 10% мінімаў — таму старая формула спявазоў не працюе. Формула для керуючых адпавядае за усуненне гэтай слепой зоны для дорогіх угод.

Дадатковая патрабовання аддзелу закупкаў, простымі словамі:

Калі значэнне угоды станавіць прынямна 500 тысяч долераў, а максімацыя компенсацыі ўскладнюецца менш чым 30% ад гэтага значэння, агент должен атрымаць санкцію керуючага пры выконанні дзеяння.

Гэты абставект выклікае ExecutiveCapRatioShape плюс пару тэстаў на pytest.

Шаг 1 — Спачатку выклікайце абракаданне

Заўжды стварайце асэрцыю раней, чым TTL.

У сучасным main гэтыя пераказы вже праходзяць. Чыба відчуць абракаданне, перайдзіце да bbeb15e (перадвыконаная версія), дадзіце тэсты, пабачыце червоны кольор, дадзіце формулу з Шага 2, а потым верніцеся да main.

Дадзіце або парабялейце гэты кэс у tests/test_shacl_constraints.py:

def test_liability_cap_below_30_percent_on_high_value_contract() -> None:
    """
    25% cap on a $2.3M contract must trigger ExecutiveCapRatioShape.
    Existing shapes (10% ratio, $100K absolute) do not catch 575K / 2.3M.
    """
    clause = ExtractedClause(
        "test-cap-ratio",
        "LiabilityClause",
        "text",
        {"liabilityCap": 575_000, "liabilityScope": "DirectDamagesOnly"},
        0.9,
        1,
    )
    graph = ClauseRDFBuilder().build(clause, 2_300_000)
    conforms, violations, _ = SHACLContractValidator().validate(graph)
    assert not conforms
    assert any(
        "30%" in v or "executive" in v.lower() for v in violations
    ), violations

def test_liability_cap_at_32_percent_no_executive_flag() -> None:
    """32.6% cap on $2.3M should not trigger the 30% executive rule."""
    clause = ExtractedClause(
        "test-cap-ratio-ok",
        "LiabilityClause",
        "text",
        {"liabilityCap": 750_000, "liabilityScope": "FullDamages"},
        0.9,
        1,
    )
    graph = ClauseRDFBuilder().build(clause, 2_300_000)
    _, violations, _ = SHACLContractValidator().validate(graph)
    cap_ratio_hits = [
        v for v in violations if "30%" in v or "executive" in v.lower()
    ]
    assert len(cap_ratio_hits) == 0, cap_ratio_hits

Выконайце:

pytest tests/test_shacl_constraints.py::test_liability_cap_below_30_percent_on_high_value_contract -v

Як выглядае цяплёны колер

До таго, калі форма існуе (на прыклад, у bbeb15e):

FAILED tests/test_shacl_constraints.py::test_liability_cap_below_30_percent_on_high_value_contract
AssertionError: ... executive ...

У ныяшнам main ідэнтычны вызов выглядае зелёным. Далей прыходзіце сам TTL — ён вялікі час існавання, які ўжо быў з’едынены вышэй, і яго воспроізводзяць, каб шаблон могаў быць викорыстаны знову.

Шаг 2 — Стварэнне формы

Дадзіце ў ontologies/contract_domain_shacl.ttl. Зберагаце cont: так, каб ён вяліў на простор імен OWL чераз сыры IRI з GitHub (ухіліцеся ад стварэння шляха /contract#, які не рашуецца):

https://raw.githubusercontent.com/cloudbadal007/ontology-rag-firewall/main/ontologies/contract_domain_owl.ttl#

Стваральнікі экзантэйнаў ствараюць URI пад тым жа базовым шляхам (…#instance/).

Павтараць на bbeb15e? Оспользуйце прымусовы патэрн URI, які ўжо є у файле SHACL той версіі. У режыме main лепш выкарыстоўваць чысты IRI, каб онтологія, форматы та тэсты былі супагодны.

cont:ExecutiveCapRatioShape a sh:NodeShape ;
    sh:targetClass cont:LiabilityClause ;
    sh:severity sh:Warning ;
    sh:message "⚠️ EXECUTIVE APPROVAL: Liability cap is below 30% of contract value. Cap ratio: {?capRatio}%. Agent action requires executive sign-off." ;
    sh:sparql [
        a sh:SPARQLConstraint ;
        sh:select """
PREFIX cont: <https://raw.githubusercontent.com/cloudbadal007/ontology-rag-firewall/main/ontologies/contract_domain_owl.ttl#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT $this ?capRatio WHERE {
  ?contract cont:hasLiabilityClause $this ;
            cont:contractValue ?v .
  $this cont:liabilityCap ?cap .
  BIND((xsd:decimal(?cap) / xsd:decimal(?v) * 100) AS ?capRatio)
  FILTER (xsd:decimal(?v) >= 500000)
  FILTER (?capRatio < 30)
}
""" ;
    ] .

Тры выборы дизайну зроблены намеравана:

  • FILTER, які выкалічвае значэнне >= 500000, прызначаны для справ з вялікімі значэннямі; тае жа прыцэнтна цыфра мае іншы значэнне для замовлення на $50K.
  • Уключэнне {?capRatio} у людскі текст дае рэвізорам точна вымерана прыцэнтна цыфру замест абстрактнага паведамлення пра апазыранне.
  • Праграма 30% — це правіла організацыі; якшо юрысты хочуць 40%, трэба зменіць гэтае значэнне. Сам файл являецца артыкулом правіла.

Шаг 3 — Спраўаць наявныя адхыленні да чытабельных пунктаў

Форматы выдаюць супакошанні машыны; захістная станова ператварае падзейкі ключоўых слоў у лініі звястака на рэжыме клазу. У main EXECUTIVE ўжо знаходзіцца сярод токенав адпаведальнасці ў firewall.py:

"LiabilityClause": ["LIABILITY", "LOW CONFIDENCE", "LEGAL REVIEW", "HIGH-VALUE", "EXECUTIVE"],

Калі переглядаеце bbeb15e, дадзіце гэты токен разам з форматам — іншаўна дэманстрацыя можа вылічыць супакошанне без прыўязкі яго да клазу адпаведальнасці.

Шаг 4 — Зноў запуск набора тэстаў і дэманстрацыі

pytest -q                         # 18 passed (entire repo)
pytest tests/test_shacl_constraints.py -v   # 8 passed (this file)
python examples/demo_offline.py

Можна чакаць завершэння всего набора за калькі секунд. У звястку дэманстрацыі з’яўляецца спецыяльная лінія для клазу адпаведальнасці (колькасць флагоў можа застацца незменнай, калі калькі супакошанняяў дзелюцца адним клазам):

⚠️ EXECUTIVE APPROVAL: Liability cap is below 30% of contract value. Cap ratio: 25.00%. Agent action requires executive sign-off.
AGENT ACTION: HALTED. Routed to human review queue.
Total value protected: $2,300,000

Адна політыка, закодаваная, падтверджаная і видныя. Гэты цыкл і є тым, што дазволяе пераходзіць да наступнага правіла домэна.

Чаму не «проста запытаць яго»?

Застосаванне таго ж 30% керавання ў системны прампт не дапамагае, калі адвакат перафразуе клазу, калі інструкцыя трапляецца ў дужа дзьвінкам контэксте, калі хтось рэдагуе прампты без урахоўвання контекста салідарнасці, або калі аудытары спытаюць, якая версія застосавала якое правіле ў які дзень.

Форма ёсць дэтэрміністычная для типаванага RDF, знаходзіцца пад кантролем версій, мае тэст на регрэсію, выдавае структураваныя доказы, укладаючы ў сабе вымераныя співважанні, і не можа зникнуць таму, што хтось прагнаў лёгкасці ў іншым месца.

Управліне для агентных систем патрабуе формальных обмежэнняя паляглых на выкарыстоўванні дадзенняў і стварэнні тэкста. Палітыка знаходзіцца ў форме; доказы — у тэстах; текст аб наявнасці аблучэння ёсць результатам аудыту.

Схема павторныя расшырэння

docs/extending.md деталізуе гэта; кароткая форма ёсць:

  1. Указаць правіле мовай, яку розумее адпаведальны за салідарнасць.
  • Расширяйце OWL толькі тады, калі трэбуюцца новыя типы або атрыбуты.
  • Даўайце адзін шэйп на кожную правілу — маленькія і аддзельныя шэйпы кращыя, чым велікі моноліт.
  • Забезпечыце, каб pytest быў цвярныя пры першым тэставанні шэйпа і зеленыя пасля яго.
  • Цільны стан: кожны шэйп мае тест; кожны тест адпавядае якой-небудзь бізнес-наследку. Змены правіл адбываюцца за певны час; системы CI атрымляюць падтверджэнняя; стан системы застаецца падлежачым перагляду.

    План развіцці палягчэння за межамі адной даговорнасці

    Сягавая захист гэткі час выкарыстоўвае толькі адну-даговорнасць модель. Існуюць два недагавораныя аспекты: падсумовванне пакетаў дадзеных у всім портфеле (examples/demo_batch_processing.py ўжо є прыкладам), а таксама контекст багацальных переходаў з боку прадавца (зберагчыце інформацыю пра інцидэнты), калі будзе створаныя граф атрыбутаў — не проста статычны URL.

    Даколі гэта не будзе рэалізавана, практыкуйце такі цыкл: напісайце шэйп, пераканаўцеся ў яго правільнасці, старанна перагляньце рэзультаты, а потым застосавайце той жа падход у наступныя сферы.

    Для кожнай формы трэба ведаць додатковы журнал — власніка, дату запуску, ідэнтыфікатор прыметкі з джерела і ідэнтыфікатор вузла pytest — так кожны рядок з паведамленням git blame стане часткай летапа аудыту. Калі змянююцца прагі, трэба версіяваць строку з паведамленням і дадзіць тэсты на межы, каб старыя прагі не моглі непазначальна вернуцца. Спрыяйце викорыстоўванню карточак «ключавая слова → клазулі» як часткі API: фіксуйце выход дэманстрацыі ў CI, каб практыкі переработкі не моглі выдаліць EXECUTIVE зі спісу токенав компенсацыі без таго, каб заданне не завершылася невынікам. Валіце аддытыўныя формы працэсу падрыхтавання над рэдагаваннем спільных блакоў SPARQL; незалежныя формы чыста вяртаюцца да пачатковага стану, калі експерымент з правіламі не задаеся. Нарэшце, публікуйце вымераны спявазанне ў кожным паведамленні, надзеюцыся на розумеўшых — рэвізоры больш даверяюць цифрам, якія можна перысчытаць з RDF, чым загальным паведамленням «трэба адзначка».