| """ |
| app.py β FinNode GraphRAG μ±λ΄ |
| ================================ |
| Hugging Face Spaces λ°°ν¬ μ§μ
μ . |
| Gradio ChatInterface + LangGraph κΈ°λ° λν νλ¦ μ μ΄. |
| |
| μ€ν: |
| python app.py |
| """ |
|
|
| from typing import List, TypedDict |
|
|
| import dotenv |
| import gradio as gr |
| from langgraph.graph import END, StateGraph |
|
|
| from src.retrieval.finRetrieval import graphrag |
|
|
| dotenv.load_dotenv() |
|
|
| |
| |
| |
| |
| |
| try: |
| graphrag._init_once() |
| print("β
[μκ° μ§λ¨ μλ£] Neo4j AuraDB μ§μ κ·Έλνμ μλ²½νκ² μ μλμμ΅λλ€!") |
| except Exception as e: |
| print(f"β [μκ° μ§λ¨ μ€ν¨] Neo4j DB μ°κ²° νμΈ μ€ μλ¬κ° λ°μνμ΅λλ€: {e}") |
| raise e |
|
|
| |
| |
| |
|
|
|
|
| class ChatState(TypedDict): |
| question: str |
| history: List[dict] |
| context: str |
| answer: str |
|
|
|
|
| |
| |
| |
|
|
| def retrieve_node(state: ChatState) -> ChatState: |
| """Node 1: GraphRAGλ‘ κ΄λ ¨ 컨ν
μ€νΈ κ²μ""" |
| try: |
| result = graphrag.search(query_text=state["question"]) |
| context = result.answer |
| except Exception as e: |
| context = f"[κ²μ μ€λ₯: {e}]" |
| return {**state, "context": context} |
|
|
|
|
| def generate_node(state: ChatState) -> ChatState: |
| """Node 2: λν νμ€ν 리λ₯Ό κ³ λ €νμ¬ μ΅μ’
λ΅λ³ μμ± |
| |
| GraphRAGκ° μ΄λ―Έ κ²μ + μμ±μ μ²λ¦¬νλ―λ‘, |
| μ¬κΈ°μλ νμ€ν 리 κΈ°λ° νμ²λ¦¬λ μΆκ° ν¬λ§·ν
λ§ μνν©λλ€. |
| """ |
| |
| |
| answer = state["context"] if state["context"] else "κ΄λ ¨ μ 보λ₯Ό μ°Ύμ μ μμ΅λλ€." |
| return {**state, "answer": answer} |
|
|
|
|
| |
| |
| |
|
|
| builder = StateGraph(ChatState) |
| builder.add_node("retrieve", retrieve_node) |
| builder.add_node("generate", generate_node) |
| builder.set_entry_point("retrieve") |
| builder.add_edge("retrieve", "generate") |
| builder.add_edge("generate", END) |
|
|
| chat_graph = builder.compile() |
|
|
|
|
| |
| |
| |
|
|
| def chat(message: str, history: list) -> str: |
| """Gradio ChatInterfaceκ° νΈμΆνλ ν¨μ. |
| |
| Args: |
| message: μ¬μ©μ μ
λ ₯ λ©μμ§ |
| history: Gradioκ° κ΄λ¦¬νλ λν νμ€ν 리 |
| [{"role": "user"/"assistant", "content": "..."}] νμ |
| |
| Returns: |
| str: μ±λ΄ λ΅λ³ |
| """ |
| if not message.strip(): |
| return "μ§λ¬Έμ μ
λ ₯ν΄ μ£ΌμΈμ." |
|
|
| |
| state: ChatState = { |
| "question": message, |
| "history": history, |
| "context": "", |
| "answer": "", |
| } |
|
|
| result = chat_graph.invoke(state) |
| return result["answer"] |
|
|
|
|
| |
| |
| |
|
|
| demo = gr.ChatInterface( |
| fn=chat, |
| chatbot=gr.Chatbot(height=500), |
| textbox=gr.Textbox(container=False, scale=7), |
| title="FinNode β AI κΈ°μ
νΈλ λ λΆμ μ±λ΄", |
| description=( |
| "> μ΅μ AI λ΄μ€λ₯Ό κΈ°λ°μΌλ‘ ꡬμΆλ μ§μ κ·Έλν(GraphRAG)μμ λ΅λ³ν©λλ€.\n\n" |
| "**μμ μ§λ¬Έ**\n" |
| "- μΌμ±μ μμ μ΅κ·Ό AI κΈ°μ νΈλ λλ?\n" |
| "- μΉ΄μΉ΄μ€κ° κ°λ° μ€μΈ AI μλΉμ€ λͺ©λ‘μ μλ €μ€\n" |
| "- μ΄λ€ κΈ°μ
μ΄ LLM κΈ°μ μ κ°λ°νλμ?\n" |
| "- μ΅κ·Ό AI κ΄λ ¨ λ΄μ€ κΈ°μ¬λ₯Ό μμ½ν΄μ€" |
| ), |
| examples=[ |
| "μΌμ±μ μμ μ΅κ·Ό AI κΈ°μ νΈλ λλ?", |
| "μΉ΄μΉ΄μ€κ° κ°λ° μ€μΈ AI μλΉμ€ λͺ©λ‘μ μλ €μ€", |
| "μ΄λ€ κΈ°μ
μ΄ LLM κΈ°μ μ κ°λ°νλμ?", |
| "μ΅κ·Ό AI κ΄λ ¨ λ΄μ€ κΈ°μ¬λ₯Ό μμ½ν΄μ€", |
| ], |
| cache_examples=False, |
| ) |
|
|
| if __name__ == "__main__": |
| demo.launch( |
| server_name="0.0.0.0", |
| server_port=7860, |
| theme=gr.themes.Soft(primary_hue="indigo") |
| ) |
|
|