Abstraktní Wikipedie/Návrh architektury systému generování přirozeného jazyka

From Meta, a Wikimedia project coordination wiki
This page is a translated version of the page Abstract Wikipedia/Natural language generation system architecture proposal and the translation is 100% complete.

Návrh Ariela Gutmana

Tento dokument popisuje navrhovanou architekturu systému pro generování přirozeného jazyka (NLG) v Abstraktní Wikipedii. Při zvažování architektury systému NLG je třeba vzít v úvahu následující skutečnosti:

  1. Modularita: systém by měl být modulární, aby bylo možné nezávisle upravovat různé aspekty NLG (např. morfosyntaktická a fonotaktická pravidla).
  2. Lexikálnost: systém by měl být schopen jak načítat lexikální data (odděleně od kódu), tak se spoléhat na produktivní jazyková pravidla pro generování těchto dat za běhu (např. skloňování anglického plurálu s -s).
  3. Rekurzivita: vzhledem ke kompoziční a rekurzivní povaze většiny jazyků,[1], by efektivní systém NLG musel být sám rekurzivní.

V souvislosti s Abstraktní Wikipedií přichází v úvahu další omezení:

  1. Rozšiřitelnost: systém by měl být přístupný rozšiřování jak jazykovými odborníky a technickými přispěvateli, tak i netechnickými a neodbornými přispěvateli, kteří pracují na různých částech systému.

Z výše uvedených omezení se zdá rozumné předpokládat, že jediná funkce Wikifunkcí (=WF) nemůže efektivně zachytit složitost takového modulárního systému NLG, ale spíše je třeba zapojit více takových funkcí, z nichž každá odpovídá za jiný krok v pipeline NLG.

V současném návrhu WF jednotlivé funkce nemohou:

  • Vyvolat další funkce WF.
  • Načíst data z externích zdrojů, jako jsou Wikidata.
  • Změnit určitý globální stav systému.

K překonání těchto omezení tento dokument navrhuje pipeline NLG, která má být spuštěna orchestrátorem WF a na kterou se žádná z těchto omezení nevztahují. Navíc, aby se mohli zapojit i netechničtí přispěvatelé, je navrženo vytvoření vlastního šablonovacího jazyka, který by mohl být spuštěn vytvořeným vyhodnocovacím nástrojem WF.

Alternativním přístupem by bylo odstranit omezení návrhu vyhodnocovacích funkcí WF a zapouzdřit celý řetězec NLG do jediné funkce WF (která by pak volala další funkce WF). Tento přístup by sice změnil některé aspekty implementace systému (např. samotná orchestrace pipeline by byla editovatelná přispěvateli WF), ale koncepční architektura by zůstala z velké části stejná.

Na konci dokumentu je uvedeno krátké srovnání s jinými navrhovanými přístupy.

Přehled architektury

Jak bylo vysvětleno výše, celá NLG pipeline nejde zapouzdřit do jediné funkce Wikifunkcí (=WF), ale musí být spuštěn orchestrátorem WF, který by umožnil načíst data z externích zdrojů (zejména z Wikidat), vyvolávat různé funkce WF (tvořené editory) a udržovat při tom potřebný stav. Předpokládaná architektura je znázorněna na následujícím diagramu, kde tmavě modré formy představují prvky, které by byly vytvořeny editory Wikifunkcí (obdélníky) nebo Wikidat (zaoblené obdélníky), zatímco světle modré prvky představují funkce nebo data existující v rámci orchestrátoru WF, a tudíž nejsou přímo přístupné editorům z komunity.

Uveďme si podrobnosti o jednotlivých krocích:

  1. Při zadání typu konstruktoru se vybere konkrétní renderer,[2] a data obsažená v daném konstruktoru jsou předána rendereru jako parametry jeho funkce.
  2. Renderer je v podstatě šablona: kombinace statického textu a slotů, které lze vyplnit parametry rendereru, lexémy z Wikidat nebo výstupem jiných rendererů. Šablony jsou relativně snadno pochopitelné a editovatelné, a tak bude autorství rendererů přístupné i netechnickým přispěvatelům.
  3. Výstupem rendereru je syntaktický strom závislostí (využívající například Universal Dependencies (UD) nebo formalismus Surface-Syntactic Universal Dependencies (SUD))[3] v níž jsou uzly nesklonné lexémy (identifikované svými lemmaty), rozšířené o některá morfologická omezení. V praxi nemusí být strom plně specifikován; zejména statický text nemusí být nutně součástí stromu.
  4. Morfologická omezení spojená se strukturou syntaktického stromu umožňují skloňování lemmat podle lexikálních údajů uvedených ve Wikidatech nebo pomocí skloňovacích tabulek gramatické specifikace. Výstupem tohoto kroku je lineární posloupnost textu, minimálně anotovaná informacemi o části řeči (tj. zda slovo představuje podstatné jméno, sloveso, předložku atd.).
  5. V tomto kroku se uplatňují fonotaktická omezení, přičemž se uplatňují jevy specifické pro daný jazyk. Ty mohou zahrnovat výběr kontextových forem (např. v angličtině a/an) nebo kontrakci sousedních forem (např. francouzské de + le = du).
  6. V závěrečném kroku čištění může být nutné upravit mezery, velká písmena a interpunkci, aby byl výsledný text uložen jako článek ve Wikipedii. Tento krok lze modelovat jazykově agnostickým způsobem pomocí (jazykově závislých) anotací z předchozích kroků.

Ve výše uvedené architektuře jsou tři složky, které musí členové komunity spravovat:

  1. Šablonovací renderery - ty tvoří většinu potřebné práce, protože každý konstruktor potřebuje jeden šablonovací renderer pro každý jazyk (i když je možné opakované použití rendererů pro části vět). Všimněte si, že termín renderer je zde použit v užším smyslu než v Architektuře vícejazyčné Wikipedie. V posledně uvedeném článku se termín renderer vztahuje na funkci end-to-end data-to-text, zatímco zde používáme termín renderer k označení konkrétní součásti NLG pipeline, konkrétně šablony. Není to náhoda, protože ve výše uvedené architektuře jsou ostatní části pipeline relativně pevné a nepotřebují neustálou kurátorskou péči členů komunity.
  2. Gramatické specifikace - ty by měly specifikovat příslušné morfologické rysy potřebné pro každý jazyk, jejich hierarchii a způsob, jakým se projevují prostřednictvím vztahů závislostí. Tyto specifikace mohou být uloženy buď jako data ve Wikidatech, nebo jako funkce ve Wikifunkcích (bude rozhodnuto). Je pravděpodobné, že tvorba a správa těchto gramatik bude vyžadovat značné lingvistické a technické znalosti, ale protože se vytvářejí jednou pro každý (lidský) jazyk, považuje se to za přijatelné.
  3. Wikidata lexémy - ty budou udržovány stejně jako dnes, ale bylo by důležité, aby funkce, které používají, byly v souladu s gramatickými specifikacemi jednotlivých jazyků.

Struktura šablon

Vzhledem k tomu, že většina potřebné práce editorů komunity bude spočívat ve vytváření šablon, je důležité, aby tento úkol byl co nejjednodušší, a zejména aby nevyžadoval žádné zkušenosti s programováním.

Podobně jako kompozici “jazyka" ve Wikifunkcích můžeme vyvinout vlastní šablonovací jazyk.[4] Šablonovací jazyk by měl umožňovat zadání lingvistického stromu (s anotacemi UD) nad třemi typy parametrů:[5]Překlad: A. Gutman.

  • Statický text
  • Konečné funkce načítající lemmata z Wikidat nebo vytvářející lemmata za běhu z jiných parametrů (např. čísla[6]).
  • Ostatní renderery

Šablonovací jazyk bude mít vyhrazený modul evaluátoru, který bude volán orchestrátorem WF. Ten bude zodpovědný za předávání výstupu různými moduly výše popsané pipeline NLG.

Příklad

Předpokládejme, že máme jednoduchý konstruktor, který vrací věk osoby:[7]

Age(
  Entity: Malala Yousafzai (Q32732)
  Age_in_years: 24
)

Pro zobrazení takového konstruktoru v angličtině použijeme zápis šablonou podobný následujícímu (jedná se o typ Z14/Implementace (Implementation)):

{
 "type": "implementation",
 "implements": "Age_renderer_en",
 "template": {
   "part": {
     "role": "subject",  # grammatical subject     
     "type": "function call",
     "function": "Resolve_Lexeme",
     "lexeme": {
        "reference": "Entity"
      }
    },
  "part": {
    "role": "root",  # root of the clause     
    "type": "function call",
    "function": "Resolve_Lexeme",
    "lexeme": {
        "value": "be"  # replace with L-id
      }
    },
  "part": {
    "role": "num",  # numerical modifier
    "of": 4,  # Part 4 (“year”)   
    "type": "function call",
    "function": "Cardinal_number",
    "number": {
        "reference": "age_in_years"  
      }
    },
   "part": {
    "role": "npadvmod", 
    "of": 5,  # Part 5 (“old”)
    "type": "function call",
    "function": "Resolve_Lexeme",
    "lexeme": {
        "value": "year"  # replace with L-id
      }
    },
  "part": {
    "role": "acomp",
    "type": "string",
        "value": "old"      
    },
}
}

Některé syntaktické role (npadvmod, acomp) nemají ve skutečnosti žádný účinek na dohodu, takže je lze vynechat.

Struktura gramatiky

Gramatika musí obsahovat následující informace:

  1. Jaké slovní druhy má jazyk.
  2. Jaké gramatické rysy jsou vhodné pro jednotlivé slovní druhy.
  3. (Případně) hierarchie typů prvků
  4. Jak gramatické vztahy (tj. závislostní vztahy) interagují s gramatickými rysy a slovními druhy.

Všimněte si, že první body lze odvodit z lexémů Wikidat dostupných pro daný jazyk, ale bylo by užitečné je explicitně uvést jako součást definice gramatiky, která by také vynucovala/ověřovala definice lexémů Wikidat.[8] Takový validátor by bylo možné napsat pro každý jazyk jako funkci WF, která by pak běžela nad lexémy Wikidat a označovala, zda jsou správně anotovány podle schématu daného jazyka.

Pokud jde o gramatické vztahy, ty mohou být zakódovány buď jako data ve Wikidatech, nebo jako funkce ve WF. Vztahy závislostí lze implementovat jako sjednocení gramatických vlastností jejich uzlů, každý vztah by bylo možné implementovat jako kompoziční funkci WF s použitím funkce Unify jako vestavěnou funkci. Například relace "subj" pro angličtinu by byla implementována následujícím způsobem (s použitím zkráceného zápisu):

subj_en(noun, verb): 
    Unify(noun.pos, NOUN);  # Validate types
    Unify(verb.pos, VERB);
    Unify(noun.number, verb.number);
    Unify(noun.person, verb.person);
    Unify(noun.case, NOMINATIVE);

Všimněte si, že takto implementovaná funkce subj není čistě funkcionální, protože ovlivňuje své vstupní argumenty (a návratová hodnota se ve skutečnosti nepoužívá, pokud nedojde k chybě sjednocení). Aby se věci zjednodušily, musel by toto speciální chování podporovat evaluátor funkcí.

Můžete chtít spojit funkce, které se sloučí. Například pokud si všimneme, že číslo a osoba jsou často spojeny, můžeme definovat dílčí funkci, jako je následující:

agr(left, right):
    Unify(left.number, right.number);
    Unify(left.person, right.person);

Pak můžeme výše uvedený vztah subj nadefinovat takto:

subj_en(noun, verb): 
    Unify(noun.pos, NOUN);  # Validate types
    Unify(verb.pos, VERB);
    agr(noun, verb);
    Unify(noun.case, NOMINATIVE);

Modulární návrh gramatik a renderů

Často se stává, že jazyky ze stejné jazykové rodiny vykazují určité gramatické a strukturní podobnosti. Tohoto jevu lze využít definováním hierarchie jazyků a jazykových rodin,[9] a umožnit systému NLG používat dynamické přijímání nejkonkrétnější implementace (pod)-renderu nebo (pod)-vztahu.

Jiné přístupy

K dnešnímu dni vím o dvou dalších systémech, které byly navrženy pro zpracování NLG Abstraktní Wikipedie.

  1. Grammatical framework (GF) je zavedený funkcionální programovací jazyk určený k podpoře vícejazyčného generování a porozumění přirozenému jazyku (viz popis v newsletteru). Má prosperující komunitu informatiků, lingvistů a dalších nadšenců, kteří do něj přispívají.
  2. Ninai/Udiron je NLG systém v Pythonu, který vytvořil člen komunity Mahir Morshed a který využívá lexémová data z Wikidat a kombinuje je pomocí UD stromů. Systém byl vytvořen s ohledem na projekt Abstraktní Wikipedie. Několik zajímavých příkladů konstruktorů a jejich vykreslení lze nalézt v demu systému Ninai.

Ačkoli se oba systémy liší, lze je porovnat s návrhem uvedeným v tomto dokumentu v podobných osách:

  • Oba systémy jsou zaměřeny na převod relativně abstraktních a složených sémantických reprezentací do gramatické struktury a následně do textu.
  • Vyžadují zvládnutí některých programovacích dovedností, ať už se jedná o doménově specifický jazyk (GF) nebo obecný programovací jazyk (Python).
  • Pořadí slov ve výstupním textu je určeno celou NLG pipeline (např. přidání operátoru Question by mohlo změnit pořadí slov v angličtině).
  • Pokud jsou definice gramatiky správné, je zaručena gramatická správnost výstupu.

Návrh uvedený v tomto dokumentu má naopak za cíl co nejvíce usnadnit přispívání lidem bez předchozích technických znalostí. To znamená následující:

  • Může pracovat s konkrétními, nekompozitními, sémantickými reprezentacemi (jako výše uvedený příklad k věku). To však nevylučuje práci s abstraktnějšími reprezentacemi.
  • Na základní úrovni nejsou k psaní šablonovacích rendererů potřeba téměř žádné programátorské dovednosti. Znalost lingvistiky (zejména závislostních anotací) může být užitečná pro dosažení gramatického výstupu a je nezbytná pro psaní samotných gramatických specifikací.
  • Pořadí slov je určeno samotnými šablonami a v dalším průběhu se nemění.
  • Výstup může být negramatický, pokud šablona nebyla správně navržena.

Poznámky pod čarou

  1. o tom, zda rekurze existuje ve všech jazycích, se v posledních letech vedou vášnivé debaty
  2. Může být užitečné umožnit uvedení konstruktoru buď nominálně (např. "Mariina svatba za Pierra"), nebo verbálně ("Marie se provdala za Pierra"). V takovém případě by bylo zapotřebí více než jeden renderer pro každý konstruktor.
  3. Formalismus SUD je jednodušší a pravděpodobně vhodnější pro úlohy NLG. O nedostatcích UD pojednává Osborne & Gerdes (2019). Srovnání obou formalismů viz také https://surfacesyntacticud.github.io/conversions/. V obou případech budeme možná muset rozšířit množinu vztahů závislostí, abychom zachytili některé vzory požadované pro NLG, jako je například vzájemná křížová reference.
  4. Šablonovací jazyk by mohl být navržen jako "syntaktický cukr" nad kompozičním jazykem, a proto by jej pravděpodobně mohl spouštět stejný evaluační program jako kompozičním jazyk.
  5. Viz poster "Using Dependency Grammars in guiding Natural Language Generation" (A. Gutman, A. Ivanov, J. Kirchner, 2019), jakož i odpovídající working paper.
  6. K vykreslování kardinálů a ordinálů v různých jazycích, stejně jako dalších datových typů, jako jsou data, lze použít knihovnu Unicode Common Locale Data Repository (CLDR)
  7. V praxi by se věk měl pravděpodobně počítat z data narození, ale pro příklad je uveden v konstruktoru. Kromě toho si můžeme představit dynamický konstruktor, ve kterém se část údajů počítá za běhu.
  8. V současné době neexistuje konzistence v anotaci lexémů, a to ani v jednom jazyce. Například tvar "has" je anotován jako "jednotné číslo, třetí osoba, prostý přítomný čas", zatímco tvar "is" je anotován jako "třetí osoba jednotného čísla, indikativ přítomného času"."
  9. V závislosti na potřebné granularitě lze použít existující hierarchické kódy definované v normě ISO 639-5, případně se spolehnout na existující hierarchii jazyků definovanou v MediaWiki.