latincy-dashboard / pages /1_parsing_demo.py
diyclassics's picture
perf: shared cached model + background preload at home page
b949170
Raw
History Blame
6 kB
import streamlit as st
import pandas as pd
import datetime
from model_helpers import load_model
st.set_page_config(page_title="Parsing Demo", layout="wide")
st.sidebar.header("Parsing Demo")
default_text = """Ita fac, mi Lucili; vindica te tibi, et tempus, quod adhuc aut auferebatur aut subripiebatur aut excidebat, collige et serva."""
def format_morph(morph):
morph = morph.to_dict()
if morph:
return ", ".join([f"{k}={v}" for k, v in morph.items()])
else:
return ""
def analyze_text(text):
doc = nlp(text)
rows = []
token_count = 0
for sent_idx, sent in enumerate(doc.sents):
sent_id = f"s{sent_idx + 1}"
sent_start = sent.start
for token_idx, token in enumerate(sent):
if token_count >= 500:
break
token_id = token_idx + 1
if token.head == token:
head = 0
else:
head = token.head.i - sent_start + 1
rows.append(
(
sent_id,
token_id,
token.text,
token.lemma_,
token.pos_,
token.tag_,
format_morph(token.morph),
head,
token.dep_,
token.ent_type_,
)
)
token_count += 1
if token_count >= 500:
break
df = pd.DataFrame(
rows,
columns=[
"sent_id",
"token_id",
"form",
"lemma",
"upos",
"xpos",
"feats",
"head",
"deprel",
"ent_type",
],
)
return df
st.title("LatinCy Text Analyzer")
# Shared, cached lg model β€” warmed at startup by the home-page preloader, so
# this returns instantly on all but the very first (cold) load.
model_name = "la_core_web_lg"
nlp = load_model(model_name)
st.write(f"Loaded model: {model_name} (v{nlp.meta['version']})")
df = None
tab1, tab2 = st.tabs(["Analyze", "About"])
with tab1:
text = st.text_area(
"Enter some text to analyze (max 500 tokens)", value=default_text, height=200
)
if st.button("Analyze"):
df = analyze_text(text)
sent_count = df["sent_id"].nunique()
st.text(f"Analyzed {len(df)} tokens in {sent_count} sentences with {model_name} model.")
st.dataframe(df, width=1200, hide_index=True)
@st.cache_data
def convert_df(df):
return df.to_csv(index=False, sep="\t").encode("utf-8")
csv = convert_df(df)
def create_timestamp():
return datetime.datetime.now().strftime("%Y%m%d%H%M%S")
# nb: clicking this button resets app! Open streamlit issue, as of 4.15.2023; cf. https://github.com/streamlit/streamlit/issues/4382
st.markdown("*NB: Clicking the download button will reset the app after download!*")
st.download_button(
"Press to Download",
csv,
f"latincy-analysis-{create_timestamp()}.tsv",
"text/csv",
key="download-csv",
)
with tab2:
st.markdown("""
## About
This demo produces a **Universal Dependencies (UD)** style tabular
analysis of Latin text, showing the full linguistic annotation that
LatinCy predicts for each token.
### What Is UD Parsing?
[Universal Dependencies](https://universaldependencies.org/) is a
framework for consistent grammatical annotation across languages.
A UD parse assigns every token its part of speech, morphological
features, and a labeled syntactic dependency linking it to its
grammatical head. The result is a complete, machine-readable
description of sentence structure.
### Output Columns
The table follows the standard
[CoNLL-U format](https://universaldependencies.org/format.html):
| Column | CoNLL-U Field | Description |
|--------|---------------|-------------|
| **sent_id** | β€” | Sentence identifier (added by this demo) |
| **token_id** | ID | Position of the token within its sentence (1-indexed) |
| **form** | FORM | The surface form exactly as it appears in the text |
| **lemma** | LEMMA | Dictionary headword (*e.g.* *tempus* for *tempora*) |
| **upos** | UPOS | Universal part-of-speech tag (NOUN, VERB, ADJ, ADV, etc.) |
| **xpos** | XPOS | Language-specific POS tag from the Latin tagset |
| **feats** | FEATS | Morphological features: Case, Number, Gender, Tense, Mood, Voice, etc. |
| **head** | HEAD | Index of the syntactic head token (0 = sentence root) |
| **deprel** | DEPREL | Dependency relation to head (*nsubj*, *obj*, *obl*, *advmod*, *amod*, etc.) |
| **ent_type** | β€” | Named entity type, if any (PER, LOC, NORP) |
### Model Details
- **Model:** `la_core_web_lg` β€” LatinCy v3.9.6
- **Training data:** Harmonized annotations from 6 UD Latin treebanks
(Perseus, PROIEL, ITTB, LLCT, UDante, CIRCSE) + LASLA
- **Framework:** [spaCy](https://spacy.io/) v3
### Accuracy (v3.9.6, lg model)
| Component | Score |
|-----------|-------|
| **POS (UPOS)** | 97.26% |
| **Morphology** | 90.37% |
| **Lemma** | 95.26% |
| **Dependency UAS** | 83.50% |
| **Dependency LAS** | 78.53% |
| **Sentence segmentation** | 92.64% F1 |
| **NER** | 87.46% F1 |
Scores evaluated on held-out UD test set; NER on dev set.
### Notes
- Output is limited to 500 tokens
- TSV export follows [CoNLL-U format](https://universaldependencies.org/format.html)
### References
- [Universal Dependencies](https://universaldependencies.org/) β€” annotation guidelines and treebank data
- [UD Latin treebanks](https://universaldependencies.org/la/index.html) β€” all Latin UD resources
- [LatinCy on HuggingFace](https://huggingface.co/latincy) β€” models and documentation
""")