Annotated_text in Streamlit

Hi,

I am using the package st-annotated-text to highlight some words in texts on my streamlit app.
However, I noticed that when the text is too long, the app shows a truncated text.
Someone had the same problem ? Is there anyway to solve this problem ?

Thanks,

1 Like

Hi @syo, welcome to the Streamlit community!

@thiago wrote this package, maybe he has some suggestions. Tagging him here for the next time he comes to the forum.

Best,
Randy

Hey @syo ,

I had the same problem once.

Following the #7 you can see that passing a height might work:

annotated_text("This is text", height=200)

If it does not work, you can still follow along the commit and change it in the package by
adding **kwargs to streamlit.components.v1.html(str(out), **kwargs) and def annotated_text(*args, **kwargs). Hope that helps.

1 Like

Hi,

Thanks @randyzwitch, I’ll tag for the next time.

Thanks @chris_klose for your help !

You’re welcome :slight_smile:

Hi Im new to streamlit…
when i try to do
annotation(sentence,"","#8cff66")
part of the sentence is not visible in UI. How to make the height dynamic

Now I modified my code to use
height = int(len(answer)) * 0.5 + 30
annotated_text( *newlist, height=height)

In newlist I have htmlcomponents like below

    newlist.append(annotation(sentence,"","#8cff66",))

Below is the output… Can you please let me know how to customize?

Is it possible to send the word position rather than the word incase there multiple words? I have JSON that contain begin and end offsets.

Hey @Jake_Vernon,

I guess this would be the common approach to store annotations in most frameworks (e.g. spacy) anyway. Was also my first thought.

Some time ago I wrote a function that splits the string before and after an entity, until there are no more entities for a sentence and then adds the end of the string. Either you hack that function quickly yourself, wait until I find it again and paste it or maybe @thiago might want to implement general support for it?

In any case I think it should be no problem if there are several identical words. The reason for it is that currently the words must be specified in sequential order. So no worries about it, Jake :slight_smile: !

doc = spacy.nlp("Streamlit is awesome.")
sents_plus_ents = map_entities(doc)
annotated_text(*sents_plus_ents)
def map_entities(doc):
        plain_text = doc.text
        entities = text.entities
        return resamble(plain_text, entities)
def resamble(plain_text, entities):
   """ Resamble the entities to fit the text_annotate style."""
    ll = []
    entities_copy = entities.copy()
    prev_ent_idx = 0
    current_ent_idx=0
    while len(entities)>0:
        if len(ll)==0:
            ll.append(plain_text[:entities[current_ent_idx]["start"]])
            ll.append( (plain_text[entities[0]["start"]:entities[0]["end"]], entities[0]["label"], ent_color_mapping[entities[0]["label"]]) )
        else:
            ll.append( plain_text[entities_copy[prev_ent_idx-1]["end"]:entities[0]["start"]] )
            ll.append ((plain_text[entities[0]["start"]:entities[0]["end"]], entities[0]["label"], ent_color_mapping[entities[0]["label"]]))
        if len(entities)>1:
            del entities[0]
            prev_ent_idx+=1
            continue
        else:
            ll.append(plain_text[entities[0]["end"]:])
            del entities[0]
    return ll
ent_color_mapping = {
    "ORG":"#faa",
    "DAT":"#00968C",
     ...
}

I guess one could do some refactoring. Anyways, you get the idea!