Spaces:
Running
Running
Restore missing agent logic
Browse files- agents/demystifier_agent.py +101 -5
agents/demystifier_agent.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
| 1 |
-
# D:\jan-contract\agents\demystifier_agent.py
|
| 2 |
|
| 3 |
import os
|
| 4 |
from typing import TypedDict, List
|
|
@@ -11,13 +10,110 @@ from langchain_community.vectorstores import FAISS
|
|
| 11 |
from langchain_core.prompts import PromptTemplate
|
| 12 |
from langchain_core.runnables import RunnablePassthrough
|
| 13 |
from langchain_core.output_parsers import StrOutputParser
|
| 14 |
-
from core_utils.core_model_loaders import load_embedding_model
|
|
|
|
| 15 |
|
|
|
|
| 16 |
embedding_model = load_embedding_model()
|
|
|
|
| 17 |
|
| 18 |
-
#
|
| 19 |
|
| 20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
# --- 4. The Master "Controller" Function ---
|
| 23 |
def process_document_for_demystification(file_path: str):
|
|
@@ -41,7 +137,7 @@ def process_document_for_demystification(file_path: str):
|
|
| 41 |
print("--- Running analysis graph for the report ---")
|
| 42 |
chunk_contents = [chunk.page_content for chunk in chunks]
|
| 43 |
# Limit context to avoid token limits if document is huge
|
| 44 |
-
graph_input = {"document_chunks": chunk_contents
|
| 45 |
|
| 46 |
result = demystifier_agent_graph.invoke(graph_input)
|
| 47 |
report = result.get("final_report")
|
|
|
|
|
|
|
| 1 |
|
| 2 |
import os
|
| 3 |
from typing import TypedDict, List
|
|
|
|
| 10 |
from langchain_core.prompts import PromptTemplate
|
| 11 |
from langchain_core.runnables import RunnablePassthrough
|
| 12 |
from langchain_core.output_parsers import StrOutputParser
|
| 13 |
+
from core_utils.core_model_loaders import load_embedding_model, load_gemini_llm
|
| 14 |
+
from langgraph.graph import StateGraph, END
|
| 15 |
|
| 16 |
+
# --- Initialize Models ---
|
| 17 |
embedding_model = load_embedding_model()
|
| 18 |
+
llm = load_gemini_llm()
|
| 19 |
|
| 20 |
+
# --- 1. RAG Chain Logic ---
|
| 21 |
|
| 22 |
+
def create_rag_chain(retriever):
|
| 23 |
+
"""Creates a RAG chain for answering questions about the document."""
|
| 24 |
+
|
| 25 |
+
template = """Answer the question based only on the following context:
|
| 26 |
+
{context}
|
| 27 |
+
|
| 28 |
+
Question: {question}
|
| 29 |
+
"""
|
| 30 |
+
prompt = PromptTemplate.from_template(template)
|
| 31 |
+
|
| 32 |
+
def format_docs(docs):
|
| 33 |
+
return "\n\n".join(doc.page_content for doc in docs)
|
| 34 |
+
|
| 35 |
+
rag_chain = (
|
| 36 |
+
{"context": retriever | format_docs, "question": RunnablePassthrough()}
|
| 37 |
+
| prompt
|
| 38 |
+
| llm
|
| 39 |
+
| StrOutputParser()
|
| 40 |
+
)
|
| 41 |
+
|
| 42 |
+
return rag_chain
|
| 43 |
+
|
| 44 |
+
# --- 2. Demystifier Graph Logic ---
|
| 45 |
+
|
| 46 |
+
class DemystifierState(TypedDict):
|
| 47 |
+
document_chunks: List[str]
|
| 48 |
+
summary: str
|
| 49 |
+
key_terms: str
|
| 50 |
+
final_report: str
|
| 51 |
+
|
| 52 |
+
def summarize_document(state: DemystifierState):
|
| 53 |
+
"""Summarizes the provided document chunks."""
|
| 54 |
+
print("---NODE: Summarizing Document---")
|
| 55 |
+
text = "\n\n".join(state["document_chunks"])
|
| 56 |
+
# Truncate for safety if too large for prompt
|
| 57 |
+
text = text[:30000]
|
| 58 |
+
|
| 59 |
+
prompt = f"""
|
| 60 |
+
You are a legal expert. Summarize the following legal document content in simple, easy-to-understand language.
|
| 61 |
+
Focus on the main purpose and parties involved.
|
| 62 |
+
|
| 63 |
+
Content:
|
| 64 |
+
{text}
|
| 65 |
+
"""
|
| 66 |
+
response = llm.invoke(prompt)
|
| 67 |
+
return {"summary": response.content}
|
| 68 |
+
|
| 69 |
+
def extract_key_terms(state: DemystifierState):
|
| 70 |
+
"""Extracts and explains key legal terms."""
|
| 71 |
+
print("---NODE: Extracting Key Terms---")
|
| 72 |
+
text = "\n\n".join(state["document_chunks"])
|
| 73 |
+
text = text[:30000]
|
| 74 |
+
|
| 75 |
+
prompt = f"""
|
| 76 |
+
Identify 5-7 complex legal terms or clauses from the text below.
|
| 77 |
+
List them and explain what they mean in plain English for a layperson.
|
| 78 |
+
|
| 79 |
+
Content:
|
| 80 |
+
{text}
|
| 81 |
+
"""
|
| 82 |
+
response = llm.invoke(prompt)
|
| 83 |
+
return {"key_terms": response.content}
|
| 84 |
+
|
| 85 |
+
def generate_report(state: DemystifierState):
|
| 86 |
+
"""Compiles the final analysis report."""
|
| 87 |
+
print("---NODE: Generating Final Report---")
|
| 88 |
+
|
| 89 |
+
report = f"""
|
| 90 |
+
# Document Analysis
|
| 91 |
+
|
| 92 |
+
## 📝 Summary
|
| 93 |
+
{state['summary']}
|
| 94 |
+
|
| 95 |
+
## 🔑 Key Terms & Definitions
|
| 96 |
+
{state['key_terms']}
|
| 97 |
+
|
| 98 |
+
## 💡 Expert Advice
|
| 99 |
+
Always consult with a qualified lawyer for critical legal decisions. This analysis is AI-generated guidance.
|
| 100 |
+
"""
|
| 101 |
+
return {"final_report": report}
|
| 102 |
+
|
| 103 |
+
# --- Build the Graph ---
|
| 104 |
+
workflow = StateGraph(DemystifierState)
|
| 105 |
+
|
| 106 |
+
workflow.add_node("summarize", summarize_document)
|
| 107 |
+
workflow.add_node("extract_terms", extract_key_terms)
|
| 108 |
+
workflow.add_node("compile_report", generate_report)
|
| 109 |
+
|
| 110 |
+
# Parallel execution of summary and terms
|
| 111 |
+
workflow.set_entry_point("summarize")
|
| 112 |
+
workflow.add_edge("summarize", "extract_terms")
|
| 113 |
+
workflow.add_edge("extract_terms", "compile_report")
|
| 114 |
+
workflow.add_edge("compile_report", END)
|
| 115 |
+
|
| 116 |
+
demystifier_agent_graph = workflow.compile()
|
| 117 |
|
| 118 |
# --- 4. The Master "Controller" Function ---
|
| 119 |
def process_document_for_demystification(file_path: str):
|
|
|
|
| 137 |
print("--- Running analysis graph for the report ---")
|
| 138 |
chunk_contents = [chunk.page_content for chunk in chunks]
|
| 139 |
# Limit context to avoid token limits if document is huge
|
| 140 |
+
graph_input = {"document_chunks": chunk_contents}
|
| 141 |
|
| 142 |
result = demystifier_agent_graph.invoke(graph_input)
|
| 143 |
report = result.get("final_report")
|