Kód belső működésének ellenőrzése automatikusan AI segítségével #2

Írtam arról korábbi blogomban, hogy nagyon hatékonynak tartom futó kódok belső változóinak állapot terét vizsgálni intelligens modellekkel. Kvázi egy élő szemantikai debug, melyet másképpen nagyon nehéz lenne felderíteni, főleg emberként. Nézzünk egy példát minta kóddal (Ruby):

def test

  # reset global variables used for intelligent inner state check
  $test_store = []
  $test_check = nil
  $test_result = nil

  1000.times {|i|
    a = 1/rand
    b = rand
    d = [ a, b ]
    c = { "something" => 1/rand, "else" => 1/rand }

    # do an intelligent inner state check
    if not( $test_result )
      $test_store << local_variables.map{|x| eval( x.to_s ) }
      $test_check = anomaly2( $test_store.last( 1000 ) )  if rand < 0.01
      if $test_check and $test_check.size > 0
        $test_result = local_variables.zip( $test_store[ $test_check[0][0] ] ).to_h
        p $test_result
      end
    end

  }
end

 

A fenti kódban a "reset" résznél csupán alaphelyzetbe állítok 3 globális változót, melyek kellenek az futásidejű intelligens értelmezéshez. Ez lehetne egyetlen globális hash objektum is, és akkor nincs nagyon szennyezve a globális namespace. Ez technikai részlet kérdés. Az olvashatóság segítéséért külön változó nevet használok.

Mi történik?

A "reset" kód után bármilyen kód állhat bármilyen funkcionalitással. Egy ciklust tettem be példának, mely belsejében új értékek generálódnak. Ez adja a belső állapot tér változást. A valós életben ez lehet egy üzleti szoftver adatainak update-je stb.

A második megjegyzés alatti rész az intelligens ellenőrzés. Ez a saját anomália detektáló megoldásomat hívja meg "anomaly2" néven, melynek csupán egy több dimenziós objektumot adok át.

 

A működés úgy néz ki, hogy automatikusan gyűjtetem a lokális változók értékeit. Ruby-ban ezek neve elérhető a "local_variables" nyelvi változóban. Tehát még meg sem kell határoznom kézzel, hogy mely változók értékeit akarom vizsgálni. Mindet vizsgálom. Az értéküket pedig az "eval" metódussal állapítom meg. De ezen változókat manuálisan is megadhatjuk.

Gyűjtöm az értéküket egy globális tömbben. Majd időnként ellenőriztetem, hogy van-e furcsa állapot.

Fel szeretném hívni a figyelmet arra, hogy nem csak natív értékeket adok be, hanem tömböt és hash objektumot is. Ezeknél az történik, hogy az értéküket kilapítom. Tehát a globális tömb mátrixának szélessége ennyivel nő.

Az utolsó 1000 értéket vizsgálom csak a sebesség növeléshez ".last(1000)" paranccsal. És a "rand < 0.01" résszel állítom be, hogy milyen gyakran fusson le az ellenőrzés. Ez időbe kerül, de így a normál futást csak ritkán szakítja meg.

Ha anomáliát detektál, akkor kiíratom a vizsgált változók értékét az anomália beállásakori állapottal.

 

Így lehet segítséget kérni egy matematikai modelltől futásidejű szemantikai ellenőrzéshez. A fenti kód kimenete:

{:i=>170,
 :a=>535.566041446413,
 :b=>0.5703866704346444,
 :d=>[535.566041446413, 0.5703866704346444],
 :c=>{"something"=>2.574872287306668, "else"=>4.552074030148502}}
=> 1000

 

Miben segíti ez a fejlesztőt?

A hibás működés sokszor a memóriában lévő objektumok értékeiben is megjelenik, de rejtett formában. Ennek a megértése nehéz, mert egy sok dimenziós mátrixról beszélünk.

Viszont ha képesek vagyunk detektálni, akkor segítséget nyújthat a hibák lenyomozásában úgy, hogy elmondja nekünk, hogy melyik objektumnak milyen értéke volt, amikor egy furcsa állapot állt be a programunkban.

Hozzászólások

Vannak kérdéseim ezzel kapcsolatban, de egyelőre csak csendben megfigyelek.

(subscribe)

Módosított verzió inicializálás szüksége nélkül, mert a glob változók úgyis üresek induláskor. Így könnyű bárhová beinjektálni:

def test
  1000.times {|i|
    a = 1/rand
    b = rand
    d = [ a, b ]
    c = { "something" => 1/rand, "else" => 1/rand }

    # ...

    # do an intelligent inner state check
    if not( $test_result )
      $test_store = []  if not( $test_store )
      $test_store << local_variables.map{|x| eval( x.to_s ) }
      $test_check = anomaly2( $test_store.last( 1000 ) )  if rand < 0.01
      if $test_check and $test_check.size > 0
        $test_result = local_variables.zip( $test_store[ $test_check[0][0] ] ).to_h
        p $test_result
      end
    end

    # ...
  }
end