Spaces:
Running
Running
File size: 6,940 Bytes
615deca 59e20bd 615deca 66e47ee 615deca 66e47ee 615deca 66e47ee 615deca 66e47ee 615deca 59e20bd 615deca 59e20bd 615deca dae1bd3 615deca dae1bd3 dcc3a83 dae1bd3 dcc3a83 dae1bd3 dcc3a83 dae1bd3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | import streamlit as st
import spacy
import pandas as pd
import datetime
import gc
import subprocess
import json
from spacy.util import registry
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")
# Using object notation
first_model = "la_core_web_lg"
first_model_version = spacy.info(first_model)["version"]
# Function to unload the current model
@st.cache_resource
def load_model(model_name):
gc.collect() # Attempt to free memory
nlp = spacy.load(model_name)
try:
if "trf_vectors" in nlp.pipe_names: # Disable trf_vectors if it exists
nlp.disable_pipe("trf_vectors")
except Exception as e:
st.warning(f"Failed to disable 'trf_vectors': {e}")
return nlp
# Function to load model in a subprocess to avoid conflicts
def load_model_in_subprocess(model_name):
script = (
"import spacy, json; "
'nlp = spacy.load("' + model_name + '"); '
"print(json.dumps(nlp.meta))"
)
result = subprocess.run(["python", "-c", script], capture_output=True, text=True)
if result.returncode != 0:
raise RuntimeError(f"Failed to load model {model_name}: {result.stderr}")
return json.loads(result.stdout)
model_name = "la_core_web_lg" # Hardcoded to use only the lg model
nlp = spacy.load(model_name) # Directly load the lg model
st.write(f"Loaded model: {model_name} (v{spacy.info(model_name)['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.8.0
- **Training data:** Harmonized annotations from 6 UD Latin treebanks
(Perseus, PROIEL, ITTB, LLCT, UDante, CIRCSE)
- **Framework:** [spaCy](https://spacy.io/) v3
### Accuracy (v3.8.0, lg model)
| Component | Score |
|-----------|-------|
| **POS (UPOS)** | 97.5% |
| **Morphology** | 94.1% |
| **Dependency UAS** | 89.1% |
| **Dependency LAS** | 85.0% |
| **Sentence segmentation** | 99.7% F1 |
Scores are macro-averaged across the six treebank test sets.
### 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
- [GitHub: diyclassics/latincy](https://github.com/diyclassics/latincy) β LatinCy source and documentation
""")
|