CoolFace
Apppublic

soumya-ai/Knowledge-Graph

sourceHugging Facemitupdated 4mo agoView on Hugging Face
0likes
app.py216 linesDownload Raw Back to root
1"""2Hugging Face Spaces entry point (Gradio).3 4Secrets: https://huggingface.co/spaces/soumya-ai/Knowledge-Graph/settings5Or use the in-app "Connect to Neo4j Aura" form if secrets are not loaded.6 7Requires src/rag_chain.py and src/retriever.py in the Space repo.8"""9 10from __future__ import annotations11 12import gradio as gr13 14from src.config import apply_runtime_config, get_config_status, settings15from src.rag_chain import ask, ask_with_context16 17EXAMPLES = [18    "What is the relationship between OpenAI and Microsoft?",19    "How does GraphRAG differ from standard RAG?",20    "What tools does LangChain integrate with for RAG?",21    "Who founded Neo4j and what query language does it use?",22]23 24 25def _format_debug(ctx) -> str:26    lines = [27        "### Retrieved context",28        "",29        f"**Retrieved:** {len(ctx.entities)} entities, "30        f"{len(ctx.graph_paths)} graph paths, {len(ctx.chunks)} chunks",31        "",32    ]33    if ctx.entities:34        lines.append("### Entities")35        for e in ctx.entities[:12]:36            lines.append(37                f"- **{e['name']}** ({e.get('type', '')}): {e.get('description', '')}"38            )39        if len(ctx.entities) > 12:40            lines.append(f"- _…and {len(ctx.entities) - 12} more_")41    if ctx.graph_paths:42        lines.append("\n### Graph paths")43        for p in ctx.graph_paths[:8]:44            lines.append(f"- {p}")45    if ctx.chunks:46        lines.append("\n### Source chunks (preview)")47        for i, c in enumerate(ctx.chunks[:3], 1):48            preview = c[:400] + ("…" if len(c) > 400 else "")49            lines.append(f"**Chunk {i}:** {preview}")50    return "\n".join(lines)51 52 53def query_graphrag(54    question: str,55    show_retrieval: bool,56    top_k: int,57) -> tuple[str, str]:58    if not question or not question.strip():59        return "Please enter a question.", ""60 61    try:62        if show_retrieval:63            result = ask_with_context(question.strip(), top_k=int(top_k))64            return result["answer"], _format_debug(result["context"])65        return ask(question.strip(), top_k=int(top_k)), ""66    except Exception as exc:67        return f"**Error:** {exc}", ""68 69 70def build_ui() -> gr.Blocks:71    with gr.Blocks(72        title="GraphRAG — Neo4j Aura + OpenAI",73        theme=gr.themes.Soft(),74    ) as demo:75        gr.Markdown(76            """77# GraphRAG — Neo4j Aura + OpenAI + LangChain78 79Ask questions over a **knowledge graph** in Neo4j Aura (vector search + graph paths + OpenAI).80            """81        )82        status_md = gr.Markdown(get_config_status())83 84        with gr.Accordion(85            "Connect to Neo4j Aura + OpenAI (use if Space secrets are missing)",86            open=not settings.neo4j_ready() or not settings.OPENAI_API_KEY,87        ):88            gr.Markdown(89                "Paste the same values as your local `.env`. "90                "Stored **only for this browser session** (not saved on Hugging Face)."91            )92            with gr.Row():93                neo4j_uri = gr.Textbox(94                    label="NEO4J_URI",95                    placeholder="neo4j+s://xxxx.databases.neo4j.io",96                    value=settings.NEO4J_URI or "neo4j+s://3c5467e4.databases.neo4j.io",97                )98                neo4j_database = gr.Textbox(99                    label="NEO4J_DATABASE",100                    value=settings.NEO4J_DATABASE or "neo4j",101                )102            with gr.Row():103                neo4j_username = gr.Textbox(104                    label="NEO4J_USERNAME",105                    value=settings.NEO4J_USERNAME or "neo4j",106                )107                neo4j_password = gr.Textbox(108                    label="NEO4J_PASSWORD",109                    type="password",110                    placeholder="Aura password",111                )112            openai_key = gr.Textbox(113                label="OPENAI_API_KEY",114                type="password",115                placeholder="sk-...",116            )117            connect_btn = gr.Button("Connect", variant="secondary")118 119        def do_connect(uri, user, pwd, db, oai_key):120            apply_runtime_config(121                neo4j_uri=uri or "",122                neo4j_username=user or "",123                neo4j_password=pwd or "",124                neo4j_database=db or "neo4j",125                openai_api_key=oai_key or "",126            )127            return test_connection_from_ui()128 129        connect_btn.click(130            do_connect,131            inputs=[neo4j_uri, neo4j_username, neo4j_password, neo4j_database, openai_key],132            outputs=[status_md],133        )134 135        with gr.Row():136            question = gr.Textbox(137                label="Your question",138                placeholder="e.g. How does GraphRAG differ from standard RAG?",139                lines=2,140                scale=4,141            )142            submit = gr.Button("Ask", variant="primary", scale=1)143 144        with gr.Row():145            show_retrieval = gr.Checkbox(146                label="Show retrieved context (entities, paths, chunks)",147                value=False,148            )149            top_k = gr.Slider(150                minimum=1,151                maximum=15,152                value=5,153                step=1,154                label="Top K chunks",155            )156 157        answer = gr.Markdown()158        retrieval = gr.Markdown(visible=False)159 160        def toggle_retrieval_panel(show: bool):161            return gr.update(visible=show)162 163        show_retrieval.change(164            toggle_retrieval_panel,165            inputs=[show_retrieval],166            outputs=[retrieval],167        )168 169        def run(q, show, k):170            ans, dbg = query_graphrag(q, show, k)171            return ans, dbg if show else ""172 173        submit.click(174            run,175            inputs=[question, show_retrieval, top_k],176            outputs=[answer, retrieval],177        )178        question.submit(179            run,180            inputs=[question, show_retrieval, top_k],181            outputs=[answer, retrieval],182        )183 184        gr.Examples(185            examples=[[ex, False, 5] for ex in EXAMPLES],186            inputs=[question, show_retrieval, top_k],187            label="Example questions",188        )189 190        gr.Markdown(191            f"""192---193**Models:** chat `{settings.OPENAI_MODEL}` · embeddings `{settings.OPENAI_EMBED_MODEL}` ({settings.OPENAI_EMBED_DIMENSIONS}d)194            """195        )196 197    return demo198 199 200def test_connection_from_ui() -> str:201    """After UI connect: refresh status banner."""202    return get_config_status()203 204 205demo = build_ui()206 207if __name__ == "__main__":208    import os209 210    port = int(os.getenv("PORT", "7860"))211    demo.queue(default_concurrency_limit=2).launch(212        server_name="0.0.0.0",213        server_port=port,214        show_error=True,215    )216