# Tesla biography recipe

> End-to-end CLI and Python workflow using `examples/en/tesla.md` with `general/biography_graph`: parse, visualize, semantic search, and Q&A with expected artifacts under the output directory.

- Repository: yifanfeng97/Hyper-Extract
- GitHub: https://github.com/yifanfeng97/Hyper-Extract
- Human docs: https://grok-wiki.com/public/docs/yifanfeng97-hyper-extract-7891c7254cdf
- Complete Markdown: https://grok-wiki.com/public/docs/yifanfeng97-hyper-extract-7891c7254cdf/llms-full.txt

## Source Files

- `examples/en/tesla.md`
- `examples/en/tesla_question.md`
- `hyperextract/templates/presets/general/biography_graph.yaml`
- `README.md`
- `hyperextract/cli/cli.py`
- `hyperextract/__init__.py`

---

---
title: "Tesla biography recipe"
description: "End-to-end CLI and Python workflow using `examples/en/tesla.md` with `general/biography_graph`: parse, visualize, semantic search, and Q&A with expected artifacts under the output directory."
---

The canonical biography walkthrough feeds `examples/en/tesla.md` through the `general/biography_graph` preset (`type: temporal_graph`), producing a persisted Knowledge Abstract under an output directory with `data.json`, `metadata.json`, and an `index/` folder for semantic `he search` / `he talk` and OntoSight visualization via `he show` or `AutoTemporalGraph.show()`.

## Recipe components

| Component | Path or ID | Role |
|-----------|------------|------|
| Source document | `examples/en/tesla.md` | English biography of Nikola Tesla (1856–1943): early life, Edison, War of Currents, Colorado Springs, Wardenclyffe, relationships, timeline |
| Sample questions | `examples/en/tesla_question.md` | Three bullet prompts for search and chat verification |
| Template preset | `general/biography_graph` | Domain YAML mapped to `AutoTemporalGraph`; extracts entities and time-stamped relations |
| Output directory | `./output/` (CLI default in README) | On-disk Knowledge Abstract consumed by `he show`, `he search`, `he talk`, `he feed`, `he info` |

The template declares bilingual support (`language: [zh, en]`) but this recipe uses `-l en` / `language="en"`.

### What `general/biography_graph` extracts

`general/biography_graph` is a `temporal_graph` template. It instructs the LLM to extract:

| Layer | Fields | Notes |
|-------|--------|-------|
| **Entities** | `name`, `type`, `description` | Types include person, location, organization, invention, event, and similar biography categories |
| **Relations** | `source`, `target`, `type`, `time`, `description` | `time` anchors events (e.g., `1884`, `1893`); relation labels render as `{type}@{time}` |

Identifier rules deduplicate by entity `name` and relation key `{source}|{type}|{target}`. Extraction guidelines require explicit text evidence—no inferred common-sense links—and use `observation_time` (defaults to today's date in `YYYY-MM-DD`) to resolve relative dates.

## Prerequisites

<Steps>
<Step title="Install Hyper-Extract">

```bash
uv tool install hyperextract
# or: uv pip install hyperextract
```

</Step>

<Step title="Configure LLM and embedder">

Provider setup is BYOC/BYOK. Any endpoint with structured output (`json_schema` or function calling) works.

```bash
he config init -k YOUR_API_KEY
```

For local vLLM, configure LLM and embedder separately. See [Configure providers](/configure-providers).

</Step>

<Step title="Confirm sample files">

From the repository root:

```bash
ls examples/en/tesla.md examples/en/tesla_question.md
```

</Step>
</Steps>

<Warning>
Knowledge templates require `--lang` / `language`. Omitting it causes `he parse` to exit with an error. Method templates ignore language and always use English prompts.
</Warning>

## CLI workflow

<Steps>
<Step title="Parse the biography">

```bash
he parse examples/en/tesla.md \
  -t general/biography_graph \
  -o ./output/ \
  -l en
```

| Flag | Purpose |
|------|---------|
| `-t general/biography_graph` | Resolve preset biography graph template |
| `-o ./output/` | Write Knowledge Abstract artifacts |
| `-l en` | Localize prompts and field descriptions to English |
| `-f` | Overwrite when output directory is non-empty |
| `--no-index` | Skip index build; run `he build-index ./output/` before search/talk |

`he parse` calls `Template.create`, `feed_text`, `dump`, `build_index` (unless `--no-index`), and dumps again with the index.

</Step>

<Step title="Inspect the Knowledge Abstract">

```bash
he info ./output/
```

Expect `Template: general/biography_graph`, `Language: en`, non-zero `Nodes` and `Edges`, and `Index: Built` when indexing ran during parse.

</Step>

<Step title="Visualize with OntoSight">

```bash
he show ./output/
```

Loads metadata from `metadata.json`, recreates the template instance, and opens an interactive graph in the browser. Nodes are entities; edges are relations labeled with type and time.

</Step>

<Step title="Run semantic search">

```bash
he search ./output/ "What are Tesla's major inventions and their significance?" -n 5
```

Additional queries from `examples/en/tesla_question.md`:

```bash
he search ./output/ "War of Currents participants"
he search ./output/ "Tesla Edison relationship"
```

`he search` requires a populated `index/` directory.

</Step>

<Step title="Chat over the graph">

Single question:

```bash
he talk ./output/ -q "How did Tesla's relationship with Edison evolve over time?"
```

Interactive session:

```bash
he talk ./output/ -i
```

Use `-n` to widen retrieved context (default `top_k=3`).

</Step>

<Step title="Optionally evolve the graph">

```bash
he feed ./output/ additional_tesla_notes.md
he build-index ./output/   # if index was stale or built with --no-index
he show ./output/
```

`he feed` reads template and language from `metadata.json` automatically.

</Step>
</Steps>

### Expected output layout

:::files
./output/
├── data.json          # entities + relations (temporal graph payload)
├── metadata.json      # template, lang, type, timestamps
└── index/             # vector store for search/chat (FAISS-backed)
:::

`data.json` holds the structured graph. `metadata.json` records at minimum:

| Key | Example value |
|-----|---------------|
| `template` | `general/biography_graph` |
| `lang` | `en` |
| `type` | `temporal_graph` |
| `created_at` / `updated_at` | ISO timestamps |

```mermaid
flowchart LR
  subgraph input
    T[examples/en/tesla.md]
  end
  subgraph runtime
    P[he parse / Template.create]
    E[LLM structured extraction]
    I[build_index + embedder]
  end
  subgraph ka["./output/ Knowledge Abstract"]
    D[data.json]
    M[metadata.json]
    X[index/]
  end
  subgraph query
    S[he search]
    C[he talk]
    V[he show / OntoSight]
  end
  T --> P --> E --> D
  P --> M
  E --> I --> X
  D --> S
  X --> S
  D --> C
  X --> C
  D --> V
```

## Python workflow

The Python path mirrors `he parse` but gives explicit control over indexing, persistence, and `observation_time`.

<CodeGroup>

```python title="Minimal (matches README)"
from hyperextract import Template

ka = Template.create("general/biography_graph", language="en")

with open("examples/en/tesla.md") as f:
    ka.feed_text(f.read())

ka.build_index()
ka.show()
```

```python title="Full lifecycle with persistence and Q&A"
from pathlib import Path
from hyperextract import Template

OUTPUT = Path("./output")

ka = Template.create(
    "general/biography_graph",
    language="en",
    observation_time="2026-06-18",  # optional; defaults to today
)

text = Path("examples/en/tesla.md").read_text(encoding="utf-8")
ka.feed_text(text)

ka.build_index()
ka.dump(OUTPUT)

# Semantic search returns (nodes, edges)
nodes, edges = ka.search("Tesla coil inventions", top_k=5)
for node in nodes:
    print(node.name, node.type)

# Chat with retrieved context
response = ka.chat("What was the War of Currents?")
print(response.content)

ka.show()

# Reload later without re-parsing
ka2 = Template.create("general/biography_graph", language="en")
ka2.load(OUTPUT)
print(ka2.chat("Summarize Tesla's career in three sentences").content)
```

```python title="Branching with parse() (non-destructive preview)"
ka = Template.create("general/biography_graph", language="en")
preview = ka.parse(Path("examples/en/tesla.md").read_text(encoding="utf-8"))
preview.build_index()
preview.show()
```

</CodeGroup>

<Tip>
`Template.create` reads LLM and embedder clients from `~/.he/config.toml` when not passed explicitly. Pass `llm_client` and `embedder` for programmatic mixed-cloud or vLLM setups.
</Tip>

### Python vs CLI equivalence

| Step | CLI | Python |
|------|-----|--------|
| Instantiate template | implicit in `he parse` | `Template.create("general/biography_graph", language="en")` |
| Extract | `feed_text` via parse | `feed_text(text)` or `parse(text)` for a new instance |
| Build index | default on parse | `build_index()` |
| Persist | `ka.dump(output_path)` | `dump(Path("./output"))` |
| Visualize | `he show ./output/` | `ka.show()` |
| Search | `he search ./output/ QUERY` | `ka.search(query, top_k=n)` → `(nodes, edges)` |
| Chat | `he talk ./output/ -q QUERY` | `ka.chat(query, top_k=n)` → `AIMessage` |

## Verification checklist

Run these checks after extraction to confirm the recipe succeeded:

| Check | Command or action | Pass signal |
|-------|-------------------|-------------|
| Artifacts exist | `ls ./output/data.json ./output/metadata.json ./output/index/` | All three present |
| Template bound | `he info ./output/` | `general/biography_graph`, `en` |
| Graph populated | `he info ./output/` | `Nodes` and `Edges` > 0 |
| Search works | `he search ./output/ "induction motor"` | JSON results returned |
| Chat grounded | `he talk ./output/ -q "Who was George Westinghouse?"` | Answer references extracted entities |
| Questions file | Loop `examples/en/tesla_question.md` bullets through `he talk` | Coherent answers per prompt |

<Check>
A successful run produces a queryable temporal graph where biography entities (Tesla, Edison, Westinghouse, Wardenclyffe Tower, AC motor, and similar) appear as nodes and dated relations (employed_by, invented, collaborated_with, and similar) appear as edges with optional `time` fields.
</Check>

## Troubleshooting

| Symptom | Cause | Fix |
|---------|-------|-----|
| `--lang is required for knowledge templates` | Missing `-l` on `he parse` | Add `-l en` |
| `Output directory already exists and is not empty` | Re-run into same path | Use `-f` or a new `-o` path |
| `Index not found` on search/talk | Parsed with `--no-index` or empty `index/` | `he build-index ./output/` |
| `No API key found` | Unconfigured provider | `he config init` or set `OPENAI_API_KEY` |
| `Not a valid Knowledge Abstract (no data.json)` | Wrong directory passed to `he show` | Point to the `-o` output folder |
| Empty or sparse graph | LLM without reliable structured output | Switch to a verified model per provider docs |
| Relative dates mis-resolved | Default `observation_time` is today | Pass `observation_time="YYYY-MM-DD"` in `Template.create` |

Enable debug logging when extraction fails silently:

```bash
export HYPER_EXTRACT_LOG_LEVEL=DEBUG
he parse examples/en/tesla.md -t general/biography_graph -o ./output/ -l en
```

## Related pages

<CardGroup>
<Card title="Quickstart" href="/quickstart">
First successful extraction with `he config init`, `he parse`, `he search`, and the Python `Template.create` path.
</Card>
<Card title="Knowledge Abstracts" href="/knowledge-abstracts">
On-disk `data.json`, `metadata.json`, and `index/` layout plus lifecycle methods.
</Card>
<Card title="Search, chat, and visualize" href="/search-chat-visualize">
`he search`, `he talk`, `he show`, and `AutoType.show()` in depth.
</Card>
<Card title="Templates vs methods" href="/templates-vs-methods">
Why domain templates like `general/biography_graph` require `--lang` while method templates do not.
</Card>
<Card title="Troubleshooting" href="/troubleshooting">
Common failure modes for missing keys, indexes, and template resolution.
</Card>
</CardGroup>
