| """ |
| 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() |
|
|
| |
| |
| |
|
|
|
|
| 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"] |
|
|
|
|
| |
| |
| |
|
|
| with gr.Blocks( |
| title="FinNode β AI κΈ°μ
νΈλ λ λΆμ μ±λ΄", |
| theme=gr.themes.Soft(primary_hue="indigo"), |
| ) as demo: |
| gr.Markdown( |
| """ |
| # π FinNode β AI κΈ°μ
νΈλ λ λΆμ μ±λ΄ |
| > μ΅μ AI λ΄μ€λ₯Ό κΈ°λ°μΌλ‘ ꡬμΆλ μ§μ κ·Έλν(GraphRAG)μμ λ΅λ³ν©λλ€. |
| |
| **μμ μ§λ¬Έ** |
| - μΌμ±μ μμ μ΅κ·Ό AI κΈ°μ νΈλ λλ? |
| - μΉ΄μΉ΄μ€κ° κ°λ° μ€μΈ AI μλΉμ€ λͺ©λ‘μ μλ €μ€ |
| - μ΄λ€ κΈ°μ
μ΄ LLM κΈ°μ μ κ°λ°νλμ? |
| - μ΅κ·Ό AI κ΄λ ¨ λ΄μ€ κΈ°μ¬λ₯Ό μμ½ν΄μ€ |
| """ |
| ) |
|
|
| chatbot = gr.ChatInterface( |
| fn=chat, |
| chatbot=gr.Chatbot( |
| height=500, |
| placeholder="μ§λ¬Έμ μ
λ ₯νλ©΄ μ§μ κ·Έλνμμ λ΅λ³μ μ°Ύμλ립λλ€.", |
| ), |
| textbox=gr.Textbox( |
| placeholder="μ: λ€μ΄λ²μ AI κΈ°μ νΈλ λλ 무μμΈκ°μ?", |
| container=False, |
| scale=7, |
| ), |
| examples=[ |
| "μΌμ±μ μμ μ΅κ·Ό AI κΈ°μ νΈλ λλ?", |
| "μΉ΄μΉ΄μ€κ° κ°λ° μ€μΈ AI μλΉμ€ λͺ©λ‘μ μλ €μ€", |
| "μ΄λ€ κΈ°μ
μ΄ LLM κΈ°μ μ κ°λ°νλμ?", |
| "μ΅κ·Ό AI κ΄λ ¨ λ΄μ€ κΈ°μ¬λ₯Ό μμ½ν΄μ€", |
| ], |
| retry_btn=None, |
| undo_btn="β©οΈ λλ리기", |
| clear_btn="ποΈ λν μ΄κΈ°ν", |
| ) |
|
|
| if __name__ == "__main__": |
| demo.launch() |
|
|