Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/arg-tech/xaif/llms.txt

Use this file to discover all available pages before exploring further.

This page walks you through everything you need to go from a blank environment to a working xAIF argument graph. You will install the xaif package, import the AIF class, build a graph by adding locutions, propositions, and argument relations step by step, and finally export the resulting structure to a pandas DataFrame. Two complete, runnable examples are provided: one that starts from plain text and one that loads a pre-existing xAIF JSON object.

Installation

1

Install the package

Install xaif from PyPI using pip. Python 3.8 or later is required.
pip install xaif
2

Import the AIF class

The entire public API is exposed through a single import:
from xaif import AIF

Example 1: Initialise from plain text

The AIF constructor accepts a plain-text string. When given a string, it automatically creates the initial L-node (locution node) and registers a default speaker, giving you a minimal but valid xAIF structure to build on. You can then call add_component() repeatedly to attach more locutions, derive propositional I-nodes from them, and wire up argument relations.
from xaif import AIF

# Initialise with a single sentence — creates L-node 0 with a default speaker
aif = AIF("First Sentence. ")

# Add a second locution (L-node 1) spoken by "Default Speaker"
aif.add_component(component_type="locution", text="Second Sentence.", speaker="Default Speaker")

# Derive an I-node (proposition) from L-node 0.
# Creates I-node 2 and a YA-node 3 linking L-node 0 → YA → I-node 2.
aif.add_component(component_type="proposition", Lnode_ID=0, proposition="First sentence.")

# Derive an I-node from L-node 1.
# Creates I-node 4 and a YA-node 5 linking L-node 1 → YA → I-node 4.
aif.add_component(component_type="proposition", Lnode_ID=1, proposition="Second sentence.")

# Add a Default Inference (RA) relation from I-node 4 to I-node 2.
# Creates an RA node and two edges: iNode_ID1 → RA → iNode_ID2.
aif.add_component(component_type="argument_relation", relation_type="RA", iNode_ID2=2, iNode_ID1=4)

# Inspect the full xAIF dict
print(aif.xaif)

# Export argument-relation pairs as a DataFrame
print(aif.get_csv("argument-relation"))

# Export locution ↔ proposition mappings as a DataFrame
print(aif.get_csv("locution"))

Understanding the output

aif.xaif is a Python dictionary that mirrors the canonical xAIF JSON structure:
{
  "AIF": {
    "nodes": [ ... ],
    "edges": [ ... ],
    "locutions": [ ... ],
    "participants": [ ... ],
    "schemefulfillments": [],
    "descriptorfulfillments": []
  },
  "text": {"txt": "..."},
  "dialog": true,
  "ova": { ... }
}
The nodes list contains every L-node, I-node, YA-node, and RA/CA/MA-node added so far. Each edge in edges records a directed fromID → toID connection. The locutions list maps each L-node to the personID of its speaker in participants. The text field is an object with a txt key holding the HTML-annotated source text, and ova holds any OVA-tool metadata (an empty object for programmatically constructed graphs). aif.get_csv("argument-relation") returns a pandas DataFrame with one row per ordered proposition pair and the following columns:
ColumnDescription
proposition1_idNode ID of the source I-node
proposition1_textText of the source proposition
proposition2_idNode ID of the target I-node
proposition2_textText of the target proposition
relationRelation label (RA, CA, MA) or None if no relation exists
All I-node pairs that do not share a direct relation are included with relation = "None", giving downstream classifiers a ready-made positive/negative training set. aif.get_csv("locution") returns the same five-column DataFrame but for L-node ↔ I-node pairs mediated by YA-nodes, with relation holding the YA-node text (e.g., "Default Illocuting").

Example 2: Initialise from an existing xAIF JSON

If you already have a JSON object conforming to the xAIF schema — for example, output from another arg-tech module — pass it directly to the AIF constructor. The object is stored as-is and all add_component / get_csv methods become available immediately.
from xaif import AIF

# A minimal xAIF JSON representing three locutions and one RA relation
xaif_data = {
  "AIF": {
    "descriptorfulfillments": None,
    "edges": [
      {"edgeID": 0, "fromID": 0, "toID": 4},
      {"edgeID": 1, "fromID": 4, "toID": 3},
      {"edgeID": 2, "fromID": 1, "toID": 6},
      {"edgeID": 3, "fromID": 6, "toID": 5},
      {"edgeID": 4, "fromID": 2, "toID": 8},
      {"edgeID": 5, "fromID": 8, "toID": 7},
      {"edgeID": 6, "fromID": 3, "toID": 9},
      {"edgeID": 7, "fromID": 9, "toID": 7}
    ],
    "locutions": [
      {"nodeID": 0, "personID": 0},
      {"nodeID": 1, "personID": 1},
      {"nodeID": 2, "personID": 2}
    ],
    "nodes": [
      {"nodeID": 0, "text": "disagreements between party members are entirely to be expected.", "type": "L"},
      {"nodeID": 1, "text": "the SNP has disagreements.", "type": "L"},
      {"nodeID": 2, "text": "it's not uncommon for there to be disagreements between party members.", "type": "L"},
      {"nodeID": 3, "text": "disagreements between party members are entirely to be expected.", "type": "I"},
      {"nodeID": 4, "text": "Default Illocuting", "type": "YA"},
      {"nodeID": 5, "text": "the SNP has disagreements.", "type": "I"},
      {"nodeID": 6, "text": "Default Illocuting", "type": "YA"},
      {"nodeID": 7, "text": "it's not uncommon for there to be disagreements between party members.", "type": "I"},
      {"nodeID": 8, "text": "Default Illocuting", "type": "YA"},
      {"nodeID": 9, "text": "Default Inference", "type": "RA"}
    ],
    "participants": [
      {"firstname": "Speaker", "participantID": 0, "surname": "1"},
      {"firstname": "Speaker", "participantID": 1, "surname": "2"}
    ],
    "schemefulfillments": None
  },
  "dialog": True,
  "ova": [],
  "text": {
    "txt": " Speaker 1 <span class=\"highlighted\" id=\"0\">disagreements between party members are entirely to be expected.</span>.<br><br> Speaker 2 <span class=\"highlighted\" id=\"1\">the SNP has disagreements.</span>.<br><br> Speaker 1 <span class=\"highlighted\" id=\"2\">it's not uncommon for there to be disagreements between party members. </span>.<br><br>"
  }
}

# Pass the dict directly — no string conversion needed
aif = AIF(xaif_data)

# Export argument-relation pairs
print(aif.get_csv("argument-relation"))
This graph encodes the inference that “disagreements between party members are entirely to be expected” (I-node 3) supports “it’s not uncommon for there to be disagreements between party members” (I-node 7) via the Default Inference RA-node 9.
Before operating on an AIF object loaded from an external source, call aif.is_valid_json_aif() to confirm the structure contains the required nodes, edges, and locutions keys. It returns True for a well-formed graph and False otherwise — useful as a lightweight guard at pipeline boundaries.
if not aif.is_valid_json_aif():
    raise ValueError("Input is not a valid xAIF structure.")

Next steps

Now that you have a working graph, explore the rest of the documentation to go deeper:
  • xAIF Format Overview — complete reference for the JSON schema, all top-level keys, and the optional extension fields used by OVA, PropositionClassifier, and other arg-tech tools.
  • AIF Class API — full method reference for AIF, including add_component, get_csv, get_speaker, is_json_aif_dialog, and internal helpers.

Build docs developers (and LLMs) love