File size: 3,825 Bytes
65e3341
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Logica Mind — Memory Playground (Hugging Face Space).

Paste any message and watch the memory engine "think": detect the language,
extract atomic facts, and tag each with an open category + a life/work dimension.
Works offline (heuristic); paste an OpenAI key to see full LLM fact extraction.
"""
import gradio as gr

from logica_mind.extract.lang import detect_language
from logica_mind.extract import LLMExtractor
from logica_mind.extract.heuristic import HeuristicExtractor
from logica_mind.extract.taxonomy import DIMENSIONS

_DIM_LABEL = {d["id"]: d["label"] for d in DIMENSIONS}
_DIM_GROUP = {d["id"]: d.get("group", "personal") for d in DIMENSIONS}
_GROUP_EMOJI = {"personal": "🧑", "project": "🧩", "organization": "🏢", "business": "💰"}

EXAMPLES = [
    ["I'm a Scorpio who loves flat whites; we just hit $45k MRR and the launch is blocked on a payments bug."],
    ["Acabei de fechar um contrato gigante com a prefeitura de Fortaleza e vou comemorar tomando um açaí na praia."],
    ["Ich arbeite in einem Berliner Fintech-Startup und treffe mich freitags mit Priya, unserer Designerin."],
    ["私は東京に住んでいて、長寿研究のためにUFCと提携しました。"],
]


def _fact_rows(facts):
    rows = []
    for f in facts:
        dim = f.dimension or ""
        label = _DIM_LABEL.get(dim, dim or "—")
        emoji = _GROUP_EMOJI.get(_DIM_GROUP.get(dim, ""), "•")
        rows.append([f.content, f.category or "—", f"{emoji} {label}"])
    return rows


def run(text, openai_key):
    text = (text or "").strip()
    if not text:
        return "Paste a message above.", []
    lang = detect_language(text)
    lang_line = f"**Detected language:** {lang}" if lang else "**Detected language:** _model will infer it_"

    mode = "🔬 Heuristic (offline, no key)"
    facts = []
    if openai_key and openai_key.strip():
        try:
            from logica_mind.llm import OpenAILLM
            ext = LLMExtractor(llm=OpenAILLM(api_key=openai_key.strip()))
            facts = ext.extract(text, [])
            mode = "🤖 LLM extraction (gpt-4o-mini)"
        except Exception as e:
            return f"{lang_line}\n\n⚠️ OpenAI error: {e}", []
    else:
        facts = HeuristicExtractor().extract(text, [])

    header = f"{lang_line}  ·  **Mode:** {mode}  ·  **{len(facts)} fact(s)**"
    return header, _fact_rows(facts)


with gr.Blocks(title="Logica Mind — Memory Playground", theme=gr.themes.Soft()) as demo:
    gr.Markdown(
        "# 🧠 Logica Mind — Memory Playground\n"
        "Paste any message and watch the open-source memory engine **think**: it detects the "
        "language, extracts atomic facts, and tags each with a category and a life/work "
        "**dimension** (34-dimension taxonomy). Works in **any language**.\n\n"
        "Offline by default (heuristic). Paste your own OpenAI key to see full LLM extraction — "
        "the key is used only for this call and never stored.\n\n"
        "⭐ [GitHub](https://github.com/Rovemark/logica-mind) · "
        "🖥️ [Live dashboard](https://huggingface.co/spaces/rovemark/logica-mind-demo) · "
        "`pip install logica-mind`"
    )
    inp = gr.Textbox(label="Your message", lines=3, placeholder="Type in any language…")
    key = gr.Textbox(label="OpenAI API key (optional — for full LLM extraction)", type="password", placeholder="sk-…")
    btn = gr.Button("🧠 Extract memory", variant="primary")
    out_md = gr.Markdown()
    out_tbl = gr.Dataframe(headers=["Fact", "Category", "Dimension"], label="Extracted facts", wrap=True)
    btn.click(run, [inp, key], [out_md, out_tbl])
    inp.submit(run, [inp, key], [out_md, out_tbl])
    gr.Examples(EXAMPLES, inputs=inp)

if __name__ == "__main__":
    demo.launch(server_name="0.0.0.0", server_port=7860)