ai
3 мин
23 августа 2026 г.
Источник: Dev.to AI Feed

Building a Dependency Parsing Tool with LLM

shashank ms
shashank ms
RSS AI Ingest
Building a Dependency Parsing Tool with LLM

Dependency parsing extracts grammatical relationships between words in a sentence. In this tutorial we will build a lightweight tool that sends text to an LLM and returns structured dependency trees in JSON. It is useful for quick linguisti...

Dependency parsing extracts grammatical relationships between words in a sentence. In this tutorial we will build a lightweight tool that sends text to an LLM and returns structured dependency trees in JSON. It is useful for quick linguistic analysis, preprocessing pipelines, or prototyping without training a custom spaCy model. What you'll need Before starting, make sure you have the following: Python 3.10 or newer An Oxlo.ai API key from https://portal.oxlo.ai The OpenAI SDK installed: pip install openai Step 1: Configure the Oxlo.ai client I keep my API key in an environment variable so it does not leak into notebooks or git history. The client setup is a single line because Oxlo.ai is fully OpenAI-compatible. import os from openai import OpenAI client = OpenAI( base_url="https://api.oxlo.ai/v1", api_key=os.environ.get("OXLO_API_KEY", "YOUR_OXLO_API_KEY") ) Step 2: Design the system prompt The prompt is the entire product here. I instruct the model to act as a Universal Dependencies parser and emit only a JSON array of token objects. I include a one-shot example so the model does not hallucinate labels outside the UD set. SYSTEM_PROMPT = """You are a dependency parser. Given a sentence, return a JSON object with a key "tokens" containing a list of every token in the sentence, in order. Each token must be an object with these exact keys: - id: 1-based index - word: the surface form - head: the id of the syntactic head, or 0 for the root - deprel: a Universal Dependencies v2 relation such as nsubj, obj, det, case, root Rules: - Do not omit punctuation. - Use head=0 and deprel="root" for exactly one token. - Return only valid JSON, no markdown fences. Example input: "She enjoys pasta." Example output: { "tokens": [ {"id": 1, "word": "She", "head": 2, "deprel": "nsubj"}, {"id": 2, "word": "enjoys", "head": 0, "deprel": "root"}, {"id": 3, "word": "pasta", "head": 2, "deprel": "obj"}, {"id": 4, "word": ".", "head": 2, "deprel": "punct"} ] }""" Step 3: Build the parsing function I use JSON mode so the model is constrained to valid JSON, then wrap the call in a small function that extracts the list and handles the occasional empty response. I default to Llama 3.3 70B because it follows structural instructions well, but you can swap in qwen-3-32b or kimi-k2.6 if you are parsing multilingual text. import json from typing import List, Dict def parse_sentence(text: str, model: str = "llama-3.3-70b") -> List[Dict]: response = client.chat.completions.create( model=model, messages=[ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": f"Parse this sentence: {text}"}, ], response_format={"type": "json_object"}, temperature=0.1, ) raw = response.choices[0].message.content parsed = json.loads(raw) return parsed.get("tokens", []) Step 4: Validate and display the tree Raw JSON is hard to read, so I add a small printer that checks for a single root and prints a simple table. This also acts as a sanity check on the model output. def print_dependencies(tokens: List[Dict]): root_count = sum(1 for t in tokens if t.get("deprel") == "root") if root_count != 1: raise ValueError(f"Expected exactly one root, found {root_count}") print(f"{'ID':>3} {'Token':4} {'Relation'}") print("-" * 32) for t in tokens: print(f"{t['id']:>3} {t['word']:4} {t['deprel']}") def to_conllu(tokens: List[Dict]) -> str: lines = [] for t in tokens: lines.append( f"{t['id']}\t{t['word']}\t_\t_\t_\t_\t{t['head']}\t{t['deprel']}\t_\t_" ) return "\n".join(lines) Step 5: Run a small test suite I feed the parser a few sentences that cover different structures: a simple transitive clause, a prepositional phrase, and a question. This lets me verify that head indices and relations look correct without writing unit tests. if __name__ == "__main__": sentences = [ "The cat sat on the mat.", "What did she build with Oxlo.ai?", "A fast, cheap parser saves hours of annotation.", ] for sent in sentences: print(f"\nSentence: {sent}") try: tokens = parse_sentence(sent) print_dependencies(tokens) except Exception as e: print(f"Error: {e}") Run it Save the script as dep_parser.py, export your key, and run it. You should see a table for each sentence. Here is the output I got for the first sentence: $ export OXLO_API_KEY="sk-..." $ python dep_parser.py Sentence: The cat sat on the mat. ID Token Head Relation -------------------------------- 1 The 2 det 2 cat 3 nsubj 3 sat 0 root 4 on 6 case 5 the 6 det 6 mat 3 obl 7 . 3 punct Wrap-up This tool is already useful for quick annotation, but you can push it further. Two concrete next steps: add a lemma field to the prompt and export the results to CoNLL-U so you can import them into annotation software, or cache responses in a local SQLite database to avoid repeating identical requests against your Oxlo.ai quota. Because Oxlo.ai uses flat per-request pricing, parsing a batch of long sentences costs the same as short ones. If you are moving from a token-based provider, that difference adds up quickly. See https://oxlo.ai/pricing for details.

Хотите внедрить ИИ в ваш бренд?

Спроектируем и развернем автономных агентов и современный цифровой стек под ваши задачи.

Рассчитать проект