| import streamlit as st |
| import streamlit.components.v1 as components |
|
|
| from lettucedetect.models.inference import HallucinationDetector |
|
|
|
|
| def create_interactive_text(text: str, spans: list[dict[str, int | float]]) -> str: |
| """Create interactive HTML with highlighting and hover effects. |
| |
| :param text: The text to create the interactive text for. |
| :param spans: The spans to highlight. |
| :return: The interactive text. |
| """ |
| html_text = text |
|
|
| for span in sorted(spans, key=lambda x: x["start"], reverse=True): |
| span_text = text[span["start"] : span["end"]] |
| highlighted_span = f'<span class="hallucination" title="Confidence: {span["confidence"]:.3f}">{span_text}</span>' |
| html_text = html_text[: span["start"]] + highlighted_span + html_text[span["end"] :] |
|
|
| return f""" |
| <style> |
| .container {{ |
| font-family: Arial, sans-serif; |
| font-size: 16px; |
| line-height: 1.6; |
| padding: 20px; |
| }} |
| .hallucination {{ |
| background-color: rgba(255, 99, 71, 0.3); |
| padding: 2px; |
| border-radius: 3px; |
| cursor: help; |
| }} |
| .hallucination:hover {{ |
| background-color: rgba(255, 99, 71, 0.5); |
| }} |
| </style> |
| <div class="container">{html_text}</div> |
| """ |
|
|
|
|
| |
| LANGUAGE_EXAMPLES = { |
| "English (en)": { |
| "model_path": "KRLabsOrg/lettucedect-base-modernbert-en-v1", |
| "lang": "en", |
| "context": "France is a country in Europe. The capital of France is Paris. The population of France is 67 million.", |
| "question": "What is the capital of France? What is the population of France?", |
| "answer": "The capital of France is Paris. The population of France is 69 million.", |
| "output_label": "Predictions" |
| }, |
| "German (de)": { |
| "model_path": "KRLabsOrg/lettucedect-210m-eurobert-de-v1", |
| "lang": "de", |
| "context": "Frankreich ist ein Land in Europa. Die Hauptstadt von Frankreich ist Paris. Die Bevölkerung Frankreichs beträgt 67 Millionen.", |
| "question": "Was ist die Hauptstadt von Frankreich? Wie groß ist die Bevölkerung Frankreichs?", |
| "answer": "Die Hauptstadt von Frankreich ist Paris. Die Bevölkerung Frankreichs beträgt 69 Millionen.", |
| "output_label": "Vorhersagen" |
| }, |
| "French (fr)": { |
| "model_path": "KRLabsOrg/lettucedect-210m-eurobert-fr-v1", |
| "lang": "fr", |
| "context": "La France est un pays d'Europe. La capitale de la France est Paris. La population de la France est de 67 millions.", |
| "question": "Quelle est la capitale de la France? Quelle est la population de la France?", |
| "answer": "La capitale de la France est Paris. La population de la France est de 69 millions.", |
| "output_label": "Prédictions" |
| }, |
| "Spanish (es)": { |
| "model_path": "KRLabsOrg/lettucedect-210m-eurobert-es-v1", |
| "lang": "es", |
| "context": "Francia es un país de Europa. La capital de Francia es París. La población de Francia es de 67 millones.", |
| "question": "¿Cuál es la capital de Francia? ¿Cuál es la población de Francia?", |
| "answer": "La capital de Francia es París. La población de Francia es de 69 millones.", |
| "output_label": "Predicciones" |
| }, |
| "Italian (it)": { |
| "model_path": "KRLabsOrg/lettucedect-210m-eurobert-it-v1", |
| "lang": "it", |
| "context": "La Francia è un paese in Europa. La capitale della Francia è Parigi. La popolazione della Francia è di 67 milioni.", |
| "question": "Qual è la capitale della Francia? Qual è la popolazione della Francia?", |
| "answer": "La capitale della Francia è Parigi. La popolazione della Francia è di 69 milioni.", |
| "output_label": "Previsioni" |
| }, |
| "Polish (pl)": { |
| "model_path": "KRLabsOrg/lettucedect-210m-eurobert-pl-v1", |
| "lang": "pl", |
| "context": "Kopernikanizm to teoria astronomiczna opracowana przez Mikołaja Kopernika, zgodnie z którą Słońce znajduje się w centrum Układu Słonecznego, a Ziemia i inne planety krążą wokół niego. Teoria ta została opublikowana w dziele 'O obrotach sfer niebieskich' w 1543 roku.", |
| "question": "Na czym polega teoria kopernikańska i kiedy została opublikowana?", |
| "answer": "Teoria kopernikańska zakłada, że Ziemia jest jednym z wielu ciał niebieskich krążących wokół Słońca. Kopernik opracował również zaawansowane równania matematyczne opisujące ruch satelitów, które zostały wykorzystane w XX wieku w programie kosmicznym NASA. Teoria została opublikowana w 1543 roku.", |
| "output_label": "Przewidywania" |
| }, |
| "Chinese (cn)": { |
| "model_path": "KRLabsOrg/lettucedect-210m-eurobert-cn-v1", |
| "lang": "cn", |
| "context": "长城是中国古代的伟大防御工程,全长超过21,000公里。它的建造始于公元前7世纪,历经多个朝代。", |
| "question": "长城有多长?它是什么时候建造的?", |
| "answer": "长城全长约50,000公里。它的建造始于公元前3世纪,仅在秦朝时期。", |
| "output_label": "预测" |
| }, |
| "LLM-Based": { |
| "method": "llm", |
| "lang": "en", |
| "context": "France is a country in Europe. The capital of France is Paris. The population of France is 67 million.", |
| "question": "What is the capital of France? What is the population of France?", |
| "answer": "The capital of France is Paris. The population of France is 69 million.", |
| "output_label": "LLM Predictions" |
| } |
| } |
|
|
|
|
| def main(): |
| st.set_page_config(page_title="Lettuce Detective", page_icon="🥬", layout="wide") |
|
|
| st.image( |
| "https://github.com/KRLabsOrg/LettuceDetect/blob/main/assets/lettuce_detective.png?raw=true", |
| width=600, |
| ) |
|
|
| st.title("LettuceDetect Multilingual Demo 🌍") |
| st.markdown("### Detect hallucinations in 7 languages") |
|
|
| |
| with st.sidebar: |
| st.header("Settings") |
| selected_language = st.selectbox( |
| "Select Language", |
| list(LANGUAGE_EXAMPLES.keys()) |
| ) |
| |
| example = LANGUAGE_EXAMPLES[selected_language] |
| |
| |
| model_method = example.get("method", "transformer") |
| |
| if model_method == "transformer": |
| model_size = st.radio( |
| "Model Size", |
| ["Base (210M)", "Large (610M)"], |
| index=0, |
| help="Base models are faster, large models are more accurate." |
| ) |
| |
| |
| openai_api_key = None |
| else: |
| |
| st.info("LLM-based detection requires an OpenAI API key") |
| openai_api_key = st.text_input("OpenAI API Key", type="password") |
| |
| st.markdown("---") |
| st.markdown("### About") |
| st.markdown( |
| "LettuceDetect identifies hallucinations by comparing answers to provided context. " |
| "Highlighted text indicates content not supported by the source material." |
| ) |
| st.markdown("[GitHub](https://github.com/KRLabsOrg/LettuceDetect) | [HuggingFace](https://huggingface.co/collections/KRLabsOrg/multilingual-hallucination-detection-682a2549c18ecd32689231ce)") |
|
|
| |
| example = LANGUAGE_EXAMPLES[selected_language] |
| |
| |
| if model_method == "transformer": |
| model_path = example["model_path"] |
| if "base" not in model_path.lower() and "large" not in model_path.lower(): |
| |
| if "210m" in model_path.lower() and "Large" in model_size: |
| model_path = model_path.replace("210m", "610m") |
| elif "610m" in model_path.lower() and "Base" in model_size: |
| model_path = model_path.replace("610m", "210m") |
| else: |
| |
| model_path = None |
|
|
| @st.cache_resource |
| def load_detector(method, model_path=None, lang=None, api_key=None): |
| try: |
| import os |
| if api_key: |
| os.environ["OPENAI_API_KEY"] = api_key |
| |
| if method == "transformer": |
| return HallucinationDetector( |
| method=method, |
| model_path=model_path, |
| lang=lang, |
| trust_remote_code=True |
| ) |
| else: |
| |
| return HallucinationDetector(method=method) |
| except Exception as e: |
| st.error(f"Error loading model: {e}") |
| return None |
|
|
| |
| with st.spinner(f"Loading {selected_language} model..."): |
| detector = load_detector( |
| method=model_method, |
| model_path=model_path, |
| lang=example["lang"], |
| api_key=openai_api_key |
| ) |
|
|
| |
| col1, col2 = st.columns(2) |
| |
| with col1: |
| st.subheader("Input") |
| context = st.text_area( |
| "Context", |
| example["context"], |
| height=150 |
| ) |
|
|
| question = st.text_area( |
| "Question", |
| example["question"], |
| height=80 |
| ) |
|
|
| answer = st.text_area( |
| "Answer", |
| example["answer"], |
| height=100 |
| ) |
|
|
| with col2: |
| st.subheader("Results") |
| if detector: |
| if st.button("Detect Hallucinations", type="primary"): |
| with st.spinner("Analyzing..."): |
| predictions = detector.predict( |
| context=[context], question=question, answer=answer, output_format="spans" |
| ) |
| |
| if predictions: |
| st.success(f"Found {len(predictions)} hallucination(s)") |
| st.markdown(f"**{example['output_label']}:**") |
| html_content = create_interactive_text(answer, predictions) |
| components.html(html_content, height=200) |
| |
| |
| with st.expander("Raw prediction data"): |
| st.json(predictions) |
| else: |
| st.info("No hallucinations detected") |
| else: |
| st.error("Model not loaded. Please check your internet connection or try a different language.") |
|
|
| |
| st.markdown("---") |
| if model_method == "transformer": |
| st.markdown(f"**Current Model:** {model_path}") |
| else: |
| st.markdown("**Method:** LLM-based hallucination detection") |
| st.markdown(f"**Language:** {example['lang']}") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|