Auto-deploy from GitHub
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- app.py +2 -226
- space/app.py +2 -226
- space/space/app.py +2 -226
- space/space/space/app.py +2 -226
- space/space/space/space/app.py +2 -226
- space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py +2 -226
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10003-10041.md +47 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10004-10143 (C06932208).md +147 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10004-10143.md +68 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10004-10156.md +55 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10004-10213.md +206 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10005-10321.md +82 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10006-10247.md +145 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10007-10345.md +326 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10009-10021.md +192 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10009-10222.md +72 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10012-10022.md +102 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10012-10024.md +29 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10012-10035.md +208 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10012-10076.md +180 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10012-10078.md +199 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10012-10079.md +61 -0
- space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10014-10051.md +56 -0
app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/app.py
CHANGED
@@ -6,8 +6,6 @@ from entity_recognition import extract_entities
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
9 |
-
import pygraphviz as pgv
|
10 |
-
import os
|
11 |
|
12 |
# Initialize FastAPI
|
13 |
app = FastAPI()
|
@@ -16,175 +14,6 @@ app = FastAPI()
|
|
16 |
class TextRequest(BaseModel):
|
17 |
text: str
|
18 |
|
19 |
-
def wrap_label(label, max_length=15):
|
20 |
-
"""Improved label wrapping with hyphenation awareness"""
|
21 |
-
if len(label) <= max_length:
|
22 |
-
return label
|
23 |
-
|
24 |
-
# Try to break at natural points
|
25 |
-
break_chars = [" ", "-", "_", "/"]
|
26 |
-
lines = []
|
27 |
-
current = ""
|
28 |
-
|
29 |
-
for char in label:
|
30 |
-
if len(current) >= max_length and char in break_chars:
|
31 |
-
lines.append(current.strip())
|
32 |
-
current = char
|
33 |
-
else:
|
34 |
-
current += char
|
35 |
-
|
36 |
-
if current:
|
37 |
-
lines.append(current.strip())
|
38 |
-
|
39 |
-
return "\\n".join(lines)
|
40 |
-
def generate_high_res_mindmap(text):
|
41 |
-
"""Generate high-quality mind map with improved visibility"""
|
42 |
-
try:
|
43 |
-
# Verify we have entities to visualize
|
44 |
-
entities = extract_entities(text)
|
45 |
-
if not any(entities.values()):
|
46 |
-
print("No entities found to generate mind map")
|
47 |
-
return None
|
48 |
-
|
49 |
-
# Create temporary directory
|
50 |
-
temp_dir = "/tmp/mindmaps"
|
51 |
-
os.makedirs(temp_dir, exist_ok=True)
|
52 |
-
output_path = os.path.join(temp_dir, "mindmap.png")
|
53 |
-
|
54 |
-
# Create graph with optimized settings
|
55 |
-
G = pgv.AGraph(
|
56 |
-
directed=True,
|
57 |
-
rankdir="TB", # Top-to-bottom layout
|
58 |
-
bgcolor="white",
|
59 |
-
fontname="Arial", # More readable font
|
60 |
-
splines="ortho", # Straight lines
|
61 |
-
overlap="false",
|
62 |
-
concentrate="true",
|
63 |
-
ratio="compress",
|
64 |
-
size="50,50", # Larger canvas
|
65 |
-
dpi="1000", # Higher resolution
|
66 |
-
pad="1.0",
|
67 |
-
nodesep="1.2", # More space between nodes
|
68 |
-
ranksep="1.5" # More vertical space
|
69 |
-
)
|
70 |
-
|
71 |
-
# Enhanced node styling for better visibility
|
72 |
-
G.node_attr.update({
|
73 |
-
"fontsize": "24", # Larger font
|
74 |
-
"fontname": "Arial Bold",
|
75 |
-
"shape": "box",
|
76 |
-
"style": "rounded,filled",
|
77 |
-
"fillcolor": "#E1F5FE",
|
78 |
-
"color": "#0288D1",
|
79 |
-
"height": "0.8",
|
80 |
-
"width": "2.0",
|
81 |
-
"penwidth": "2.0",
|
82 |
-
"margin": "0.3,0.1" # Better text padding
|
83 |
-
})
|
84 |
-
|
85 |
-
# Enhanced edge styling
|
86 |
-
G.edge_attr.update({
|
87 |
-
"color": "#616161",
|
88 |
-
"penwidth": "2.5",
|
89 |
-
"arrowsize": "1.2",
|
90 |
-
"fontname": "Arial",
|
91 |
-
"fontsize": "20",
|
92 |
-
"fontcolor": "#424242"
|
93 |
-
})
|
94 |
-
|
95 |
-
# Add central node with improved styling
|
96 |
-
G.add_node("DOCUMENT",
|
97 |
-
shape="doubleoctagon",
|
98 |
-
fillcolor="#4FC3F7",
|
99 |
-
fontsize="28",
|
100 |
-
width="2.5",
|
101 |
-
height="1.0",
|
102 |
-
penwidth="3.0")
|
103 |
-
|
104 |
-
# Add entities with better spacing
|
105 |
-
max_categories = 5
|
106 |
-
max_entities = 8
|
107 |
-
|
108 |
-
for cat_idx, (category, values) in enumerate(entities.items()):
|
109 |
-
if cat_idx >= max_categories:
|
110 |
-
break
|
111 |
-
|
112 |
-
# Main category node
|
113 |
-
cat_node = f"CAT_{cat_idx}"
|
114 |
-
G.add_node(cat_node,
|
115 |
-
label=wrap_label(category, 18),
|
116 |
-
shape="tab",
|
117 |
-
fillcolor="#81D4FA",
|
118 |
-
fontsize="22")
|
119 |
-
|
120 |
-
G.add_edge("DOCUMENT", cat_node,
|
121 |
-
label="contains",
|
122 |
-
penwidth="3.0")
|
123 |
-
|
124 |
-
# Add entities with grouping if needed
|
125 |
-
if len(values) > max_entities:
|
126 |
-
# Create subcategory groups
|
127 |
-
for sub_idx, group in enumerate([values[i:i+max_entities]
|
128 |
-
for i in range(0, len(values), max_entities)]):
|
129 |
-
sub_node = f"SUB_{cat_idx}_{sub_idx}"
|
130 |
-
G.add_node(sub_node,
|
131 |
-
label=f"Group {sub_idx+1}",
|
132 |
-
shape="folder",
|
133 |
-
fillcolor="#B3E5FC")
|
134 |
-
G.add_edge(cat_node, sub_node)
|
135 |
-
|
136 |
-
for ent_idx, value in enumerate(group):
|
137 |
-
ent_node = f"ENT_{cat_idx}_{sub_idx}_{ent_idx}"
|
138 |
-
G.add_node(ent_node,
|
139 |
-
label=wrap_label(value, 15),
|
140 |
-
shape="note",
|
141 |
-
fillcolor="#E1F5FE")
|
142 |
-
G.add_edge(sub_node, ent_node)
|
143 |
-
else:
|
144 |
-
# Directly add entities
|
145 |
-
for ent_idx, value in enumerate(values[:max_entities]):
|
146 |
-
ent_node = f"ENT_{cat_idx}_{ent_idx}"
|
147 |
-
G.add_node(ent_node,
|
148 |
-
label=wrap_label(value, 15),
|
149 |
-
shape="note",
|
150 |
-
fillcolor="#E1F5FE")
|
151 |
-
G.add_edge(cat_node, ent_node)
|
152 |
-
|
153 |
-
# Generate output with multiple attempts
|
154 |
-
for engine in ['dot', 'neato', 'sfdp']:
|
155 |
-
try:
|
156 |
-
G.draw(output_path,
|
157 |
-
format="png",
|
158 |
-
prog=engine,
|
159 |
-
args=f"-Gdpi=300 -Gsize=50,50 -Goverlap=prism")
|
160 |
-
print(f"Successfully generated with {engine}")
|
161 |
-
|
162 |
-
# Verify the output
|
163 |
-
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
164 |
-
return output_path
|
165 |
-
|
166 |
-
except Exception as e:
|
167 |
-
print(f"Layout engine {engine} failed: {str(e)}")
|
168 |
-
continue
|
169 |
-
|
170 |
-
raise RuntimeError("All layout engines failed")
|
171 |
-
|
172 |
-
except Exception as e:
|
173 |
-
print(f"Mind map generation failed: {str(e)}")
|
174 |
-
# Create error visualization
|
175 |
-
try:
|
176 |
-
import matplotlib.pyplot as plt
|
177 |
-
plt.figure(figsize=(20, 10))
|
178 |
-
plt.text(0.5, 0.5,
|
179 |
-
f"Mind Map Generation Failed\n{str(e)}\n\nOriginal Text:\n{text[:200]}...",
|
180 |
-
ha='center', va='center', wrap=True)
|
181 |
-
plt.axis('off')
|
182 |
-
error_path = os.path.join(temp_dir, "error_mindmap.png")
|
183 |
-
plt.savefig(error_path, bbox_inches='tight', dpi=300)
|
184 |
-
plt.close()
|
185 |
-
return error_path
|
186 |
-
except:
|
187 |
-
return None
|
188 |
@app.post("/summarize")
|
189 |
def summarize_text(request: TextRequest):
|
190 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
@@ -223,16 +52,7 @@ def generate_word_cloud(request: TextRequest):
|
|
223 |
|
224 |
# Gradio UI
|
225 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
226 |
-
|
227 |
-
max-height: none !important;
|
228 |
-
min-width: 100% !important;
|
229 |
-
object-fit: contain !important;
|
230 |
-
background: white !important;
|
231 |
-
border: 1px solid #e0e0e0 !important;
|
232 |
-
border-radius: 8px !important;
|
233 |
-
padding: 20px !important;
|
234 |
-
}
|
235 |
-
.gradio-container { max-width: 1400px !important; }
|
236 |
""") as iface:
|
237 |
|
238 |
gr.Markdown("# JFK Document Analysis Suite")
|
@@ -272,20 +92,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
272 |
width=600
|
273 |
)
|
274 |
|
275 |
-
|
276 |
-
with gr.Row():
|
277 |
-
mindmap_btn = gr.Button(
|
278 |
-
"Generate Enhanced Mind Map",
|
279 |
-
variant="primary"
|
280 |
-
)
|
281 |
-
|
282 |
-
with gr.Row():
|
283 |
-
output_mindmap = gr.Image(
|
284 |
-
label="High-Resolution Mind Map",
|
285 |
-
elem_classes="mindmap-container",
|
286 |
-
height=800,
|
287 |
-
width=800
|
288 |
-
)
|
289 |
|
290 |
# Event handlers must be inside the Blocks context
|
291 |
process_btn.click(
|
@@ -294,37 +101,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
|
|
294 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
295 |
)
|
296 |
|
297 |
-
def display_mindmap(text):
|
298 |
-
try:
|
299 |
-
img_path = generate_high_res_mindmap(text)
|
300 |
-
if img_path and os.path.exists(img_path):
|
301 |
-
return img_path
|
302 |
-
return None
|
303 |
-
except Exception as e:
|
304 |
-
print(f"Display error: {e}")
|
305 |
-
return None
|
306 |
-
|
307 |
-
mindmap_btn.click(
|
308 |
-
fn=display_mindmap,
|
309 |
-
inputs=full_doc_text,
|
310 |
-
outputs=output_mindmap,
|
311 |
-
api_name="generate_mindmap",
|
312 |
-
show_progress=True
|
313 |
-
)
|
314 |
-
|
315 |
-
# Add CSS for better image display
|
316 |
-
css = """
|
317 |
-
.mindmap-container img {
|
318 |
-
max-width: 100% !important;
|
319 |
-
height: auto !important;
|
320 |
-
background: white !important;
|
321 |
-
border: 2px solid #e0e0e0 !important;
|
322 |
-
border-radius: 8px !important;
|
323 |
-
padding: 10px !important;
|
324 |
-
margin: 10px auto !important;
|
325 |
-
display: block !important;
|
326 |
-
}
|
327 |
-
"""
|
328 |
|
329 |
if __name__ == "__main__":
|
330 |
iface.launch(
|
|
|
6 |
from wordcloud import WordCloud
|
7 |
from summarization import summarizer
|
8 |
from utils import list_files, process_file
|
|
|
|
|
9 |
|
10 |
# Initialize FastAPI
|
11 |
app = FastAPI()
|
|
|
14 |
class TextRequest(BaseModel):
|
15 |
text: str
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
@app.post("/summarize")
|
18 |
def summarize_text(request: TextRequest):
|
19 |
chunks = [request.text[i:i+500] for i in range(0, len(request.text), 500)]
|
|
|
52 |
|
53 |
# Gradio UI
|
54 |
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
55 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
""") as iface:
|
57 |
|
58 |
gr.Markdown("# JFK Document Analysis Suite")
|
|
|
92 |
width=600
|
93 |
)
|
94 |
|
95 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
# Event handlers must be inside the Blocks context
|
98 |
process_btn.click(
|
|
|
101 |
outputs=[full_doc_text, output_summary, output_entities, output_wordcloud]
|
102 |
)
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
if __name__ == "__main__":
|
106 |
iface.launch(
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10003-10041.md
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# 104-10003-10041 2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
2 |
+
|
3 |
+
☐ UNCLASSIFIED
|
4 |
+
☐ INTERNAL ONLY
|
5 |
+
☐ CONFI**I**NTIAL
|
6 |
+
☑ SECRET
|
7 |
+
|
8 |
+
## ROUTING AND RECORD SHEET
|
9 |
+
|
10 |
+
SUBJECT: (Optional)
|
11 |
+
|
12 |
+
Clipping of article "The Kennedy Murder and the Secret Services of the USA"
|
13 |
+
|
14 |
+
FROM:
|
15 |
+
|
16 |
+
WE/4/INT Arthur P. Iorio
|
17 |
+
|
18 |
+
EXTENSION NO.
|
19 |
+
|
20 |
+
DATE: 26 March 1964
|
21 |
+
|
22 |
+
TO: (Officer designation, room number, and building) | DATE | OFFICER'S INITIALS | COMMENTS (Number each comment to show from whom to whom. Draw a line across column after each comment.)
|
23 |
+
-----|------|-------|-----
|
24 |
+
1. CI Staff Birch O'Neil Room 2603 | RECEIVED | FORWARDED | The attached article, which may be of interest to you, appeared in the 7 March issue of the Italian Communist Party weekly Rinascita. The writer, Gianfranco Corsini, has been on and off US correspondent for the Italian Communist press. Note that in the section pencille in red rumors are referred which suggest that kind it was the Agency to organize the murder of President Kennedy.
|
25 |
+
2. | | |
|
26 |
+
3. | | |
|
27 |
+
4. | | |
|
28 |
+
5. | | |
|
29 |
+
6. | | |
|
30 |
+
7. | | |
|
31 |
+
8. | | |
|
32 |
+
9. | | |
|
33 |
+
10. | | |
|
34 |
+
11. | | |
|
35 |
+
12. | | |
|
36 |
+
13. | | |
|
37 |
+
14. | | |
|
38 |
+
15. | | 18 |
|
39 |
+
|
40 |
+
FORM 610 USE PREVIOUS EDITIONS 3-62
|
41 |
+
|
42 |
+
☑ SECRET
|
43 |
+
☐ CONFIDENTIAL
|
44 |
+
☐ INTERNAL USE ONLY
|
45 |
+
☐ UNCLASSIFIED
|
46 |
+
|
47 |
+
Clipping not retained
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10004-10143 (C06932208).md
ADDED
@@ -0,0 +1,147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
104-10004-10143
|
2 |
+
2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
3 |
+
|
4 |
+
Date: 05/08/96
|
5 |
+
Page: 1
|
6 |
+
|
7 |
+
JFK ASSASSINATION SYSTEM
|
8 |
+
IDENTIFICATION FORM
|
9 |
+
|
10 |
+
AGENCY INFORMATION
|
11 |
+
|
12 |
+
AGENCY : CIA
|
13 |
+
RECORD NUMBER : 104-10004-10143
|
14 |
+
RECORD SERIES : JFK
|
15 |
+
AGENCY FILE NUMBER : 201-289248
|
16 |
+
|
17 |
+
DOCUMENT INFORMATION
|
18 |
+
|
19 |
+
ORIGINATOR : CIA
|
20 |
+
FROM :
|
21 |
+
TO :
|
22 |
+
TITLE : DISCUSSION BETWEEN MEMBER SR DIVISION CONCERNING
|
23 |
+
OSWALD'S STAY IN HELSINKI.
|
24 |
+
DATE : 06/01/64
|
25 |
+
PAGES : 2
|
26 |
+
SUBJECTS : HELSINKI TRIP
|
27 |
+
USSR CONSULATE
|
28 |
+
|
29 |
+
DOCUMENT TYPE : PAPER, TEXTUAL DOCUMENT
|
30 |
+
CLASSIFICATION : SECRET
|
31 |
+
RESTRICTIONS : 1B
|
32 |
+
CURRENT STATUS : RELEASED WITH DELETIONS
|
33 |
+
DATE OF LAST REVIEW : 06/12/93
|
34 |
+
OPENING CRITERIA :
|
35 |
+
COMMENTS : OSW10:V43 1993.06.12.10:33:55:150000:
|
36 |
+
|
37 |
+
[R] ITEM IS RESTRICTED
|
38 |
+
NW 64937 Docld:32106269 Page 1
|
39 |
+
|
40 |
+
INTERNAL
|
41 |
+
USE ONLY
|
42 |
+
CO DENTIAL
|
43 |
+
SECRET
|
44 |
+
ROUTING AND RECORD SHEET
|
45 |
+
|
46 |
+
SUBJECT: (Optional)
|
47 |
+
|
48 |
+
FROM: CIRA/PS
|
49 |
+
2823
|
50 |
+
|
51 |
+
TO: (Officer designation, room number, and
|
52 |
+
building)
|
53 |
+
DATE
|
54 |
+
SX-25605
|
55 |
+
1 June 64
|
56 |
+
|
57 |
+
OFFICER'S
|
58 |
+
INITIALS
|
59 |
+
COMMENTS (Number each comment to show from whom
|
60 |
+
to whom. Draw a line across column after each comment.)
|
61 |
+
RECEIVED
|
62 |
+
FORWARDED
|
63 |
+
1.
|
64 |
+
IPIAN
|
65 |
+
5 MAR 1975
|
66 |
+
Phoe assign
|
67 |
+
SX # and
|
68 |
+
clamefs to
|
69 |
+
2.
|
70 |
+
3.
|
71 |
+
4.
|
72 |
+
5.
|
73 |
+
IP JEDI
|
74 |
+
6.
|
75 |
+
201-289248
|
76 |
+
7.
|
77 |
+
8.
|
78 |
+
IPIFILES
|
79 |
+
Document Number 716-838
|
80 |
+
for FOIA Review on JUN 1976
|
81 |
+
|
82 |
+
Ath Pori, Millen
|
83 |
+
10.
|
84 |
+
11.
|
85 |
+
12.
|
86 |
+
13.
|
87 |
+
14.
|
88 |
+
15.
|
89 |
+
FORM 610 USE PREVIOUS
|
90 |
+
NW-64937 DocId 32906269 Page 2
|
91 |
+
CONFIDENTIAL
|
92 |
+
INTERNAL
|
93 |
+
USE ONLY
|
94 |
+
UNCLASSIFIED
|
95 |
+
|
96 |
+
MEMO FOR THE RECORD
|
97 |
+
1 June 1964.
|
98 |
+
SX-25605
|
99 |
+
Discussion betroen MOMBOR SR. Divisiong
|
100 |
+
and CoS Helsinki CONCERNING timetable
|
101 |
+
OF OSWALD'S stay in and Holsinki
|
102 |
+
|
103 |
+
1. At 0900 this morning I talked with Frank Friberg recently
|
104 |
+
returned COS Helsinki re Warren Commission inquiry concerning
|
105 |
+
the timetable of Oswald's stay in Finland in October 1959, including
|
106 |
+
his contact with the Soviet Consulate there. (Copy of the Commission
|
107 |
+
letter of 25 May 64 and State Cable of 22 May 64 attached.)
|
108 |
+
|
109 |
+
2. Friberg gave me the following information:
|
110 |
+
|
111 |
+
a. It takes 25 minutes to drive from the airport to
|
112 |
+
downtown Helsinki;
|
113 |
+
|
114 |
+
b. By taxi, it would take no more than 5 minutes to
|
115 |
+
reach the Soviet consulate;
|
116 |
+
|
117 |
+
C. The Soviet consulate probably closed at 1300 hours local
|
118 |
+
time on Saturdays in 1959;
|
119 |
+
|
120 |
+
d. Passenger lists (manifests) at the U.S. Consulate in
|
121 |
+
Helsinki are retained for six months only and then are destroyed.
|
122 |
+
Mr. Robert Fulton (CIA) was U.S. consular official there at
|
123 |
+
the time.
|
124 |
+
|
125 |
+
e. A copy of State's cable inquiry would go to the Helsinki
|
126 |
+
Station and they would assist in preparation of a reply.
|
127 |
+
|
128 |
+
3. Mr. Friberg agreed that it would be worthwhile to cable che
|
129 |
+
Station concerning points not covered by State in their inquiry. He
|
130 |
+
suggested changes incorporated into the cable sent to Helsinki.
|
131 |
+
|
132 |
+
Lee H. Wigren
|
133 |
+
C/SR/CI/R
|
134 |
+
|
135 |
+
Document Number
|
136 |
+
for FOIA Review on.
|
137 |
+
716-838
|
138 |
+
JUN 1976
|
139 |
+
SAME AS RELEASED
|
140 |
+
DOC
|
141 |
+
340
|
142 |
+
|
143 |
+
RECORD COPY
|
144 |
+
1
|
145 |
+
1 Jun 64
|
146 |
+
201-289248
|
147 |
+
NW 64937 Docld:32106269 Page 3
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10004-10143.md
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
10.00000
|
2 |
+
104-10004-10143 2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
3 |
+
|
4 |
+
13-00000
|
5 |
+
|
6 |
+
MEMO FOR THE RECORD 1 June 1964
|
7 |
+
Sx-25605
|
8 |
+
|
9 |
+
DISCUSSION between members SR Division,
|
10 |
+
and CoS Helsinki concerning timetable
|
11 |
+
OF OSWALD'S stay in Finland and Helsinki
|
12 |
+
|
13 |
+
1. At 0900 this morning I talked with Frank Friberg recently
|
14 |
+
returned COS Helsinki re Warren Commission inguiry concerninge.
|
15 |
+
the timetable of Oswald's stay in Finland in October 1959, including
|
16 |
+
his contact with the Soviet Consulate therer. (Copy of the Commission
|
17 |
+
letter of 25 May 64 and State Cable of 22 May, 64, attached.)
|
18 |
+
|
19 |
+
2. Friberg gave me the following information:
|
20 |
+
|
21 |
+
a. It takes 25 minutes to drive from the airport to
|
22 |
+
Helsinki.
|
23 |
+
|
24 |
+
b. By taxi, it would take no more than 5 minutes to
|
25 |
+
reach the Soviet consulate;
|
26 |
+
|
27 |
+
c. Consulate in Helsinki was open Saturdays in 1959;
|
28 |
+
|
29 |
+
d. Passenger lists (manifests) at the Helsinki airports of
|
30 |
+
Helsinki are retained for six months only and then are destroyed.
|
31 |
+
Mr. Robert Fulton (CIA) was U.S. consular official there at
|
32 |
+
the time.
|
33 |
+
|
34 |
+
e. A copy of State's cable inquiry would go to the Helsinki
|
35 |
+
Station and they would assist in preparation of a reply.
|
36 |
+
|
37 |
+
3. Mr. Friberg agreed that it would be worthwhile to cable the
|
38 |
+
Station concerning points not covered by State in their inquiry. He
|
39 |
+
suggested changes incorporated into the cable sent to Helsinki.
|
40 |
+
|
41 |
+
Lee H. Wigren
|
42 |
+
C/SR/CI/R
|
43 |
+
TRAVEL PROGRAM
|
44 |
+
IP/EDI ABSTRACTA
|
45 |
+
INDEX
|
46 |
+
IP/FIS
|
47 |
+
IP/PH
|
48 |
+
PREPARE FOR FICKING
|
49 |
+
FILM
|
50 |
+
CODE NO. (2,3,4)
|
51 |
+
RYBAT REST CODE
|
52 |
+
ISO/DCU
|
53 |
+
CABLE IDEN (11)
|
54 |
+
NTD (8)
|
55 |
+
IP/FILES
|
56 |
+
FOR FILING
|
57 |
+
|
58 |
+
Document Number 716-838
|
59 |
+
for FOIA Review on JUN 1976
|
60 |
+
SAME AS RELEASED
|
61 |
+
DOC -340
|
62 |
+
|
63 |
+
RECORD COPY
|
64 |
+
|
65 |
+
1. Jun 64
|
66 |
+
201-289248
|
67 |
+
|
68 |
+
Box 8
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10004-10156.md
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
10.00000
|
2 |
+
104-10004-10156
|
3 |
+
2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
4 |
+
|
5 |
+
Box 8
|
6 |
+
|
7 |
+
13-00000
|
8 |
+
|
9 |
+
1 June 1964
|
10 |
+
|
11 |
+
MEMO FOR THE RECORD
|
12 |
+
|
13 |
+
1. At 0900 this morning I talked with Frank Friberg recently
|
14 |
+
returned COS Helsinki re Warren Commission inquiry concerning
|
15 |
+
the timetable of Oswald's stay in Finland in October 1959, including
|
16 |
+
his contact with the Soviet Consulate there. (Copy of the Commission
|
17 |
+
letter of 25 May 64 and State Cable of 22 May 64 attached.)
|
18 |
+
|
19 |
+
2. Friberg gave me the following information:
|
20 |
+
|
21 |
+
a. It takes 25 minutes to drive from the airport to
|
22 |
+
downtown Helsinki;
|
23 |
+
|
24 |
+
b. By taxi, it would take no more than 5 minutes to
|
25 |
+
reach the Soviet consulate;
|
26 |
+
|
27 |
+
c. The Soviet consulate probably closed at 1300 hours local
|
28 |
+
time on Saturdays in 1959;
|
29 |
+
|
30 |
+
d. Passenger lists (manifests) at the U.S. Consulate in
|
31 |
+
Helsinki are retained for six months only and then are destroyed.
|
32 |
+
Mr. Robert Fulton (CIA) was U.S. consular official there at
|
33 |
+
the time.
|
34 |
+
|
35 |
+
e. A copy of State's cable inquiry would go to the Helsinki
|
36 |
+
Station and they would assist in preparation of a reply.
|
37 |
+
|
38 |
+
3. Mr. Friberg agreed that it would be worthwhile to cable the
|
39 |
+
Station concerning points not covered by State in their inquiry. He
|
40 |
+
suggested changes incorporated into the cable sent to Helsinki.
|
41 |
+
|
42 |
+
Document Number 780-340
|
43 |
+
|
44 |
+
FAIA Review on JUN 1976
|
45 |
+
|
46 |
+
SAME AS 716-838
|
47 |
+
|
48 |
+
ZONET
|
49 |
+
|
50 |
+
13-00000
|
51 |
+
|
52 |
+
See Sanitized File
|
53 |
+
Number 335
|
54 |
+
For steril
|
55 |
+
H
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10004-10213.md
ADDED
@@ -0,0 +1,206 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
104-10004-10213 2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
2 |
+
|
3 |
+
SECRET
|
4 |
+
|
5 |
+
YF2-27221
|
6 |
+
9 July 1964
|
7 |
+
|
8 |
+
MEMORANDUM FOR THE RECORD
|
9 |
+
SUBJECT : Discussion with Warren Commission Staff Member
|
10 |
+
REFERENCE: Letter from J. Lee Rankin, General Counsel of the
|
11 |
+
President's Commission, to Mr. Richard Helms
|
12 |
+
dated 3 July 1964
|
13 |
+
|
14 |
+
>O SRICE DISCUSSION with SLAUSEN & Tily on .girations.
|
15 |
+
Svitt felicy towards design woats HALETICONS ANd
|
16 |
+
CUINT Visa Puccedures,
|
17 |
+
1. With the approval of C/SR and the DDP, I met with Mr. W.
|
18 |
+
David Slawson of the staff of the President's Commission on the
|
19 |
+
Assassination of President Kennedy at 1400 hours on this date in
|
20 |
+
the Commission's offices at 200 Maryland Avenue, N.E., Washington,
|
21 |
+
D.C. The purpose of this meeting was to discuss apparent inconsistencies
|
22 |
+
in material provided the Commission by CIA and by the Department of
|
23 |
+
State which were called to our attention in a letter from the General
|
24 |
+
Counsel of the Commission to Mr. Helms, dated 3 July 1964.
|
25 |
+
|
26 |
+
2. By way of introduction, Mr. Slawson said that in the portion of the
|
27 |
+
Commission's report that he was writing, he would have to deal with the
|
28 |
+
question of whether or not the OSWALDs' departure from the USSR - and
|
29 |
+
the circumstances (i.e. timing) of that departare were unusual or
|
30 |
+
suspicious in any way. He expressed his belief that they probably were
|
31 |
+
not and cited Soviet relaxation in such matters in the post-Stalin era.
|
32 |
+
However, he wanted to be sure in his own mind that our information was
|
33 |
+
not in conflict with that which the Commission had received from State
|
34 |
+
since all of that information would remain in the records of the
|
35 |
+
Commission.
|
36 |
+
|
37 |
+
3. After stating my belief that there was no real disagreement or
|
38 |
+
inconsistency between the information from CLA and that from State, I
|
39 |
+
expressed the view that the matter resolved itself into three questions:
|
40 |
+
|
41 |
+
Document Number 767-864
|
42 |
+
for FOIA Review on
|
43 |
+
/a. Do the Soviet
|
44 |
+
JUN 1976
|
45 |
+
|
46 |
+
CS COPY
|
47 |
+
|
48 |
+
SECRET
|
49 |
+
|
50 |
+
a. Do the Soviet authorities normally permit Soviet
|
51 |
+
citizens married to foreign nationals to emigrate from the
|
52 |
+
Soviet Union to the homelands of their spouses?
|
53 |
+
|
54 |
+
b. Do they normally permit such Soviet citizens to
|
55 |
+
accompany (i.e. depart simultaneously with) their spouses
|
56 |
+
from the Soviet Union?
|
57 |
+
|
58 |
+
c. How long does it take such Soviet citizens to get
|
59 |
+
Soviet exit visas for such a purpose (time lapse from application
|
60 |
+
to granting of visas)?
|
61 |
+
|
62 |
+
4. Concerning the first two questions (3a and 3b above) I pointed out.
|
63 |
+
that we had addressed ourselves mainly to the question of Sovie: citizens
|
64 |
+
being allowed to accompany their spouses abroad while State dealt only
|
65 |
+
with the larger question of Soviets married to foreigners being allowed
|
66 |
+
to emigrate without reference to whether or not they left simultaneously
|
67 |
+
with or at another time from their spouses. Mr. Slawson commented
|
68 |
+
that this explanation was most helpful and he reread what both we and
|
69 |
+
State had said in that light.
|
70 |
+
|
71 |
+
5. By way of further explanation, I said that the statements in
|
72 |
+
paragraph 6 of our memorandum of 6 April 1964 concerning Soviets being
|
73 |
+
permitted to accompany their foreign spouses abroad were based on a
|
74 |
+
review of 26 cases, of which 10 involved Americans. In only four of
|
75 |
+
these cases did a Soviet wife leave the USSR in the company of her foreign
|
76 |
+
husband; in 14 of the cases the foreign spouse departed alone; and in the
|
77 |
+
remaining seven cases insufficient details are known to permit us to
|
78 |
+
categorize them. I added that although State's information began by
|
79 |
+
citing the issuance of 724 quota and non-quota immigrant visas by the
|
80 |
+
American Embassy in Moscow during the period FY 1954 to December
|
81 |
+
1963, it did not indicate how many of these visas were for Soviet citizens
|
82 |
+
who had married U.S. nationals. Actually State provided detailed
|
83 |
+
information for only sixteen cases and did not indicate in many of these
|
84 |
+
whether or not the Soviet was permitted to accompany the foreign spouse.
|
85 |
+
16. In response to
|
86 |
+
|
87 |
+
-2-
|
88 |
+
|
89 |
+
6. In response to a question from Mr. Slawson I stated that most
|
90 |
+
of the 26 cases upon which we based our statements involved foreign
|
91 |
+
students, exchange teachers and other relatively transient persons,
|
92 |
+
and while a number of cases have certain points in common, they bear
|
93 |
+
little similarity to the OSWALD case in that none involved a defector who
|
94 |
+
married prior to repatriating. I noted that paragraph 6 of our 6 April
|
95 |
+
1964 memorandum to the Commission had pointed this out. Mr. Slawson
|
96 |
+
indicated that he was now satisfied on this matter.
|
97 |
+
|
98 |
+
7. Concerning the length of time taken by Soviet authorities to
|
99 |
+
process exit visas for Soviet citizens married to foreign nationals
|
100 |
+
(question 3c above), I stated that, in my opinion, the information
|
101 |
+
provided by State (in the third enclosure to Mr. Meeker's letter)
|
102 |
+
substantially corresponded to the views expressed in paragraphs 6 and 7
|
103 |
+
of our memorandum to the Commission dated 6 April 1964. Mr. Slawson
|
104 |
+
asked if it would be possible to elaborate paragraph 7 of our memorandum
|
105 |
+
of 6 April by providing a statistical breakdown of the cases on which our
|
106 |
+
statements were based. I indicated that this could be done.
|
107 |
+
|
108 |
+
8. At this point Mr. Slawson stated that as a result of our discussion
|
109 |
+
he felt that the question of possible inconsistencies bad been resolved.
|
110 |
+
However, he asked that we send a brief written reply to the Commission's
|
111 |
+
letter of 3 July 1964 embodying the substance of what I had said concerning
|
112 |
+
the basis for statements included in our 6 April 1964 memorandum. (This
|
113 |
+
would include the gist of the draft reply to the Commission which I showed
|
114 |
+
to C/SR on 8 July plus an elaboration of our statements concerning Soviet
|
115 |
+
visa applications.]
|
116 |
+
|
117 |
+
9. Mr. Slawson indicated that he would be sending parts of his report
|
118 |
+
dealing with the Soviet intelligence services to CIA for checking as to
|
119 |
+
their accuracy. He did not say when this would occur.
|
120 |
+
|
121 |
+
10. After concluding the meeting with Mr. Slawson, I read Volume 52
|
122 |
+
of the transcript of testimony before the Commission. This included the
|
123 |
+
reinterview of Marina OSWALD.
|
124 |
+
|
125 |
+
-3-
|
126 |
+
|
127 |
+
Lee H. Wigren
|
128 |
+
C/SR/CI/Research
|
129 |
+
|
130 |
+
@Do. sors normally permit Sov. cityens married to for
|
131 |
+
natla to engrate pom Sll to homeland of sprise ?
|
132 |
+
• State says you - cites 724 visa applicationم
|
133 |
+
(perbably minority Spouse's; mij
|
134 |
+
belatives ite ast mijint)
|
135 |
+
- We cite absence of law; do not say.
|
136 |
+
|
137 |
+
2 arimally
|
138 |
+
② Do Sros permit sou. cits menit to fon marks to
|
139 |
+
accompany (ie depont simultanernely co.) spouses
|
140 |
+
from Sele to homelandes of spouses
|
141 |
+
- State does not say
|
142 |
+
se cite evidence that they do not
|
143 |
+
We ليه
|
144 |
+
|
145 |
+
③ How long does it take Soveits to gel. Sevivians
|
146 |
+
at to homelan Ss of fou Spouses?
|
147 |
+
to junge at
|
148 |
+
-Our #7 and State's inse
|
149 |
+
فه
|
150 |
+
Cases inhuid. it ikurus ajrec
|
151 |
+
|
152 |
+
Notes, Hedin
|
153 |
+
Co
|
154 |
+
CS-COPY
|
155 |
+
|
156 |
+
dil Ite XAA2-27221
|
157 |
+
|
158 |
+
Le 7
|
159 |
+
with) friin sprστασις
|
160 |
+
Based on in de la 26 Cail
|
161 |
+
fre till out c/ SU.
|
162 |
+
(10 US)
|
163 |
+
|
164 |
+
-Safe left line oftenband - 4
|
165 |
+
-
|
166 |
+
-
|
167 |
+
-
|
168 |
+
-
|
169 |
+
- 7- !
|
170 |
+
|
171 |
+
② Irifi in fu 47
|
172 |
+
1-2 fine taken by for allite
|
173 |
+
bisa apple of Sor Spencer of fin
|
174 |
+
substant illy agrees is lite o infe
|
175 |
+
نر
|
176 |
+
4. on Juice taken by Sri-st. poreias veda
|
177 |
+
aggelies of Sou woofcitis (1)
|
178 |
+
|
179 |
+
Gust of State is w
|
180 |
+
life cancion y bar, tibi of tense to her bij de citthoritie
|
181 |
+
1.
|
182 |
+
bun cits in Sel
|
183 |
+
life in the poor
|
184 |
+
/
|
185 |
+
740
|
186 |
+
li inquest for norme of all 1152
|
187 |
+
ت
|
188 |
+
:/ cits vitus ricerit'd in Cast
|
189 |
+
2: 10 quo cesta Collis len, the of
|
190 |
+
fine betinien intrs of aggler. l. He apport
|
191 |
+
by God auth
|
192 |
+
2 יני
|
193 |
+
|
194 |
+
Aun cat
|
195 |
+
0063
|
196 |
+
>
|
197 |
+
|
198 |
+
② Date of appplectenfor os doit reser
|
199 |
+
Ion dedures, in 14
|
200 |
+
12
|
201 |
+
|
202 |
+
"
|
203 |
+
[10dayo-194]
|
204 |
+
Promplit all itthees
|
205 |
+
-10 line to 14 yeю
|
206 |
+
- Cant till bord
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10005-10321.md
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
2 |
+
|
3 |
+
CLASSIFIED MESSAGE
|
4 |
+
|
5 |
+
SECRETARTDAT
|
6 |
+
|
7 |
+
30 September 64 FILE NO. 201-4524
|
8 |
+
|
9 |
+
BONN, FRANKFURT, BERLIN, COPENHAGEN,
|
10 |
+
REYKJAVIK, PARIS, STOCKHOLM
|
11 |
+
DIRECTOR THE HAGUE BRUSSELS
|
12 |
+
|
13 |
+
nue, stess, cluez, VR, FILE
|
14 |
+
|
15 |
+
UN, FRAN, BRLN, COPENJO GMNY
|
16 |
+
E. PARI, STOC, muda, Hagu, Beas
|
17 |
+
|
18 |
+
AT/KUDESK/TPMURILLO / CATIJA
|
19 |
+
|
20 |
+
KIGREST TRACES JOACHIM JOESTER DPOB 29 JUL 07 COLOGNE.
|
21 |
+
|
22 |
+
ENTER ENTIRE ADULT CAREER AND AUTHOR CA 30 BOOKS AND NUMEROUS
|
23 |
+
SPAPER ARTICLES. POST WWII WORKS VERY ANTI-KUBARK, LAST
|
24 |
+
OK TITLE - OSWALD: ASSASSIN OR FALL GUY? HAS WRITTEN UNDER
|
25 |
+
UE NAME AND UNDER PSEUDONYMS: FRANZ VON NESSELRODE; H.F.
|
26 |
+
LIKIN; WALTER KELL; PAUL DELATHUIS.
|
27 |
+
|
28 |
+
2. ACCORDING CAPTURED GESTAPO DOCS HE JOINED GERM CP ON
|
29 |
+
MAY 32 AND HAD MEMBERSHIP NO. 532315. OWNED LENDING LIBRARY
|
30 |
+
LN AND SOME TIME AFTER MAY 32 WENT USSR WHERE REMAINED UNTIL
|
31 |
+
|
32 |
+
33. DURING ABSENCE HIS LIBRARY MANAGED BY FIANCEE ANNA
|
33 |
+
SCHINSKY. LAST RESIDENCE GERMANY BRLN LUETZOWSTRASSE 40
|
34 |
+
BEI HESS.
|
35 |
+
|
36 |
+
Document Number 888-906
|
37 |
+
for FOIA Review on JUL 1976
|
38 |
+
|
39 |
+
CONTINUED
|
40 |
+
|
41 |
+
COORDINATING OFFICERS
|
42 |
+
GROUP 1
|
43 |
+
Excluded from automatic
|
44 |
+
downgrading and
|
45 |
+
declassification
|
46 |
+
AUTHENTICAT
|
47 |
+
OFFICER
|
48 |
+
|
49 |
+
SECRET/RYB
|
50 |
+
REPRODUCTION BY OTHER THAN THE ISSUING OFFICE IS PROHIBITED.
|
51 |
+
|
52 |
+
3. IN MAY 33 FLED TO FRANCE, WAS IN COPE 36-37 BUT EXPELLED
|
53 |
+
(OR LEFT) EDCAUSE HIS ANTI-DAHISK GOVT WAITINGS. LEFT DENMARK
|
54 |
+
FOR FRANCE VIA ICELAND. IN 40 IN SWEDEN, MARRIED MAY NILSSON,
|
55 |
+
CAME US VIA USSR IN 41 AND NATURALIZED CITIZEN SINCE 48
|
56 |
+
|
57 |
+
4. WOULD APPRECIATE AS FULL A CHECK AS POSSIBLE, INCLUDING
|
58 |
+
LOCAL SERVICES AND AVAILABLE OVERT LOCAL PRE-WWL REFERENCES
|
59 |
+
(PRESS, BOOKS, ETC.) ON JOESTEN AND FIANCEE.
|
60 |
+
|
61 |
+
5. FOR BAIN: PLS ALSO CHECK DDC AND REQUEST PHOTOSTATS
|
62 |
+
ANY DOCS, CAN ADDRESS AND NAME HESS BE CHECKED? ANY CHANCE
|
63 |
+
LOCATE FIANCEE?
|
64 |
+
|
65 |
+
6. ALL ADDRESSERS PLS HANDLE AEQUEST URGENTLY AS MATTER
|
66 |
+
ALSO OF INTEREST TO WARREN COMMISSION. CABLE SUMMARY RESULTS
|
67 |
+
AND POUCH DETAILS INCLUDING ALL COPIES AVAILABLE JOESTEN PRE
|
68 |
+
WWI WRITINGS.
|
69 |
+
|
70 |
+
CONTINUED
|
71 |
+
|
72 |
+
SEGRET/RVRAT
|
73 |
+
|
74 |
+
MIC PARASI THROUGK 3 AECVI IN PUBLIC DOMAIN, AUS
|
75 |
+
FILE
|
76 |
+
END OF MESSAGE
|
77 |
+
|
78 |
+
C/EE/06
|
79 |
+
C/WE/L
|
80 |
+
CAVELS
|
81 |
+
|
82 |
+
SEGRET/RVRAT
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10006-10247.md
ADDED
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
104-10006-10247
|
2 |
+
2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
3 |
+
SECRET
|
4 |
+
FROM: (Requesters name)
|
5 |
+
BRANCH
|
6 |
+
ROOM
|
7 |
+
BADGE NO.
|
8 |
+
NAME CHECK AND CONSOLIDATION REQUEST
|
9 |
+
EXTENSION
|
10 |
+
DATE
|
11 |
+
RID CONTROL NO.
|
12 |
+
TO
|
13 |
+
TUBE
|
14 |
+
ROOM
|
15 |
+
DATE
|
16 |
+
INITIALS
|
17 |
+
RID/INDEX
|
18 |
+
DT-5
|
19 |
+
REQUESTER
|
20 |
+
RID/FILES
|
21 |
+
DT-6
|
22 |
+
REQUESTER
|
23 |
+
RID/ANALYSIS GT-7
|
24 |
+
RID/201
|
25 |
+
DW-6
|
26 |
+
RID/MIS
|
27 |
+
GT-6
|
28 |
+
RID/INDEX
|
29 |
+
DT-5
|
30 |
+
|
31 |
+
SUBJECT TO BE CHECKED
|
32 |
+
SURNAME
|
33 |
+
(All spellings)
|
34 |
+
D'EDKOV, Roman Fedorovich er Vilasa Nikolaevna
|
35 |
+
SPELLING VARIATIONS TO BE CHECKED
|
36 |
+
AKA, ALIASES
|
37 |
+
OTHER IDENTIFYING DATA (Occupation, sex, CP membership,
|
38 |
+
I. S. affiliations, etc.)
|
39 |
+
Poss. at soo. Eulest. Ind
|
40 |
+
RESIDENCE
|
41 |
+
New Delhi, Ind
|
42 |
+
SEX DATE OF BIRTH
|
43 |
+
PLACE OF BIRTH
|
44 |
+
CITIZENSHIP
|
45 |
+
USSR
|
46 |
+
Minse USSR
|
47 |
+
|
48 |
+
RESULTS OF RID/INDEX CHECK
|
49 |
+
COMMENTS
|
50 |
+
NO PERTINENT IDENTIFIABLE INFORMATION
|
51 |
+
CARD REFERENCES ATTACHED
|
52 |
+
|
53 |
+
INSTRUCTIONS FOR REQUESTERS
|
54 |
+
IN ALL CASES
|
55 |
+
1. Use gummed label; type or print all
|
56 |
+
entries.
|
57 |
+
2. Upon receipt of index card reproductions
|
58 |
+
draw a green diagonal line across the
|
59 |
+
items you do not want.
|
60 |
+
3. Edit (use green) the reproduced index
|
61 |
+
cards to indicate:
|
62 |
+
(a) cards to be destroyed (mark with
|
63 |
+
green D and note reason for destruction)
|
64 |
+
Examples: document destroyed; duplicate
|
65 |
+
or less informative than retained in-
|
66 |
+
formation; information of no CS value.
|
67 |
+
|
68 |
+
(b) corrections and additions, inclu-
|
69 |
+
ding infinity symbol ∞ when card in-
|
70 |
+
cludes all facts contained in the
|
71 |
+
document.
|
72 |
+
|
73 |
+
Note 1. Records of COI, SSU, OSS and CIG
|
74 |
+
are in RID/ARD, and those that meet
|
75 |
+
indexing criteria in CSHB 70-1-l are
|
76 |
+
carded in the CS Main Index. If you
|
77 |
+
believe there could be additional in-
|
78 |
+
formation of value in these records,
|
79 |
+
you must request an Archives Index
|
80 |
+
search.
|
81 |
+
201 CONSOLIDATION
|
82 |
+
1. Return this form with the card repro-
|
83 |
+
ductions, also return pertinent documents,
|
84 |
+
aperture cards and the dossier if a 201 on
|
85 |
+
the subject exists.
|
86 |
+
2. For each document to be included in the
|
87 |
+
consolidation (i.e., copy or cross reference
|
88 |
+
to be placed in the 201 file), green D the
|
89 |
+
corresponding card and check (a) or (b)
|
90 |
+
below:
|
91 |
+
|
92 |
+
(a) Consolidate into
|
93 |
+
201-
|
94 |
+
(b) Open 201 file on subject.
|
95 |
+
|
96 |
+
RESTRICTION (If any)
|
97 |
+
CRYPTONYM
|
98 |
+
OTHER INTERESTED DESKS OR STATIONS
|
99 |
+
ASSIGNED
|
100 |
+
YES
|
101 |
+
NO
|
102 |
+
FILE TO
|
103 |
+
BE KEPT
|
104 |
+
RID
|
105 |
+
DESK
|
106 |
+
Note 2. Information concerning foreign
|
107 |
+
public personalities (except mili-
|
108 |
+
tary) may be available in BR/OCR
|
109 |
+
x7997.
|
110 |
+
DATE
|
111 |
+
SIGNATURE OF RECORDS OFFICER
|
112 |
+
|
113 |
+
13-00000
|
114 |
+
|
115 |
+
One Roman Fedorovich DEDKOV, born 28 March 1927 in Ariansk, USSR,
|
116 |
+
|
117 |
+
and his wife Vilasa Nikolayevna DEDKOV, born 31 December 1930 in Minsk,
|
118 |
+
USSR, applied for were listed as applicants for entry visas to Indiad
|
119 |
+
sometime prior to April 1962. DEDKOV, who was issued Soviet passport
|
120 |
+
number 207461 on 17 September 1960, was scheduled to arrive in New Delhi
|
121 |
+
for two years as an English language teacher at the Soviet Embassy.
|
122 |
+
|
123 |
+
It is not known whether or not DEDKOV actually arrived in New Delhi.
|
124 |
+
|
125 |
+
Not at sent because it shows lioman to Indonians, aaring
|
126 |
+
"Home List" nut classified.
|
127 |
+
SCAT
|
128 |
+
10 AUG 1964
|
129 |
+
|
130 |
+
13-00000
|
131 |
+
|
132 |
+
INDIA 1
|
133 |
+
|
134 |
+
DEDKOV, Roman Fedorovich
|
135 |
+
|
136 |
+
Subj scheduled to arrive New Delhi for two years as an
|
137 |
+
English teacher at the Soviet Embassy; Ppt 207461 iss
|
138 |
+
17 Sept 60 (Mos Comment: Subj is presumed to have arr
|
139 |
+
sometime after sept 60). NBDA-8509, 24 Apr 62
|
140 |
+
|
141 |
+
Wife: Vilasa Nikolayevna (DPOB: 31 Dec 1930; Minsk)
|
142 |
+
|
143 |
+
201-756978
|
144 |
+
|
145 |
+
DPOB: 28 Mar 1927; Ariansk
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10007-10345.md
ADDED
@@ -0,0 +1,326 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
2 |
+
|
3 |
+
ROUTING AND RECORD SHEET
|
4 |
+
|
5 |
+
SUBJECT: Document Number 988-927 BD
|
6 |
+
|
7 |
+
for FOIA Review on SEP 1976
|
8 |
+
|
9 |
+
FROM: Chief, CI/R&A
|
10 |
+
2 C 17
|
11 |
+
|
12 |
+
TO: Chief, AF
|
13 |
+
7 C 32
|
14 |
+
|
15 |
+
Chief, EE
|
16 |
+
3 D 31 07
|
17 |
+
|
18 |
+
Chief, FE
|
19 |
+
5 D 31 07
|
20 |
+
|
21 |
+
Chief, NE
|
22 |
+
6 D 31 07
|
23 |
+
|
24 |
+
Chief, WE
|
25 |
+
4 B 44 05
|
26 |
+
|
27 |
+
Chief, WH
|
28 |
+
3 B 44 03
|
29 |
+
|
30 |
+
DDP
|
31 |
+
3 C 20 16
|
32 |
+
|
33 |
+
CI/R&A
|
34 |
+
2 C 17
|
35 |
+
|
36 |
+
PSD
|
37 |
+
|
38 |
+
RID
|
39 |
+
|
40 |
+
DATE 27-865
|
41 |
+
24 December 1964
|
42 |
+
|
43 |
+
For Coordination
|
44 |
+
|
45 |
+
DEFERRED
|
46 |
+
|
47 |
+
RID PROUESTING STOPPED
|
48 |
+
PLEASE INDICATE HANDLING
|
49 |
+
|
50 |
+
NOTE: This Document of the CA R
|
51 |
+
of the CS Decur
|
52 |
+
Desired Handling
|
53 |
+
For Signature and Release
|
54 |
+
BY HAND
|
55 |
+
PLEASE CALL
|
56 |
+
|
57 |
+
Easy Printing 201-289248
|
58 |
+
|
59 |
+
DISPATCH
|
60 |
+
|
61 |
+
Chiefs of all Stations
|
62 |
+
|
63 |
+
Chief, KUDOVE
|
64 |
+
|
65 |
+
Warren Commission Testimony - Selected Excerpts
|
66 |
+
|
67 |
+
FYI
|
68 |
+
|
69 |
+
1. The Warren Commission's Report on the assassination of
|
70 |
+
President Kennedy focused attention on the magnitude of the problem.
|
71 |
+
involved in the protection of the Chief Executive. As you know, it is
|
72 |
+
our responsibility, overseas and in headquarters, to render every
|
73 |
+
support possible to the Secret Service in the conduct of its statutory
|
74 |
+
responsibilities in the United States, and especially when the President
|
75 |
+
travels abroad,
|
76 |
+
|
77 |
+
2. The circumstances confronting the Warren Commission
|
78 |
+
produced discussion and testimony on various aspects of the problem
|
79 |
+
of Presidential protection and on interagency operational cooperation,
|
80 |
+
which normally do not find their way into the public domain. These
|
81 |
+
include the acquisition and dissemination of information, consultation,
|
82 |
+
coordination, and operational interchanges. I believe you will be
|
83 |
+
interested in the attached extracts of testimony given before the Warren
|
84 |
+
Commission by U.S. intelligence and security officials. Pertinent
|
85 |
+
Fortions have been side lined. I commend these materials for reading
|
86 |
+
by all officers in positions of senior responsibility in headquarters and
|
87 |
+
overseas.
|
88 |
+
|
89 |
+
Document Number 988-927 BD.
|
90 |
+
|
91 |
+
for FOIA Review on SEP 1976
|
92 |
+
|
93 |
+
FLETCHER M. KNIGHT
|
94 |
+
201-289245
|
95 |
+
|
96 |
+
Book Dispatch No. 4726
|
97 |
+
|
98 |
+
100-300-12
|
99 |
+
|
100 |
+
Raymond G. Rocca gwh
|
101 |
+
|
102 |
+
HQ COPY
|
103 |
+
DISPATCH
|
104 |
+
|
105 |
+
Distribution For
|
106 |
+
Book Dispatch No. 4726
|
107 |
+
|
108 |
+
AF Division
|
109 |
+
Abidjan
|
110 |
+
Accra
|
111 |
+
Addis Ababa
|
112 |
+
Algiers
|
113 |
+
Bamako
|
114 |
+
Brazzaville
|
115 |
+
Bujumbura
|
116 |
+
Conakry
|
117 |
+
Dakar
|
118 |
+
Dar-es-Salaam
|
119 |
+
Freetown
|
120 |
+
Kampala
|
121 |
+
Khartoum
|
122 |
+
Lagos
|
123 |
+
Leopoldville
|
124 |
+
Lome
|
125 |
+
Lusaka
|
126 |
+
Mogadiscio
|
127 |
+
Monrovia
|
128 |
+
Nairobi
|
129 |
+
Pretoria
|
130 |
+
Rabat
|
131 |
+
Salisbury
|
132 |
+
Tananarive
|
133 |
+
Tripoli
|
134 |
+
Tunis
|
135 |
+
Yaounde
|
136 |
+
|
137 |
+
The above listing has been
|
138 |
+
reviewed in the AF Division.
|
139 |
+
|
140 |
+
dw
|
141 |
+
|
142 |
+
EE Division
|
143 |
+
Athens
|
144 |
+
Bern
|
145 |
+
Frankfurt
|
146 |
+
Nicosia
|
147 |
+
Vienna
|
148 |
+
|
149 |
+
The above listing has been
|
150 |
+
reviewed in the EE Division.
|
151 |
+
|
152 |
+
FE Division
|
153 |
+
Bangkok
|
154 |
+
Djakarta
|
155 |
+
Hong Kong
|
156 |
+
Honolulur
|
157 |
+
Kuala Lumpur
|
158 |
+
Manila
|
159 |
+
Melbourne
|
160 |
+
Okinawa
|
161 |
+
Phnom Penh
|
162 |
+
Rangoon
|
163 |
+
Saigon
|
164 |
+
Seoul
|
165 |
+
Taipei
|
166 |
+
Tokyo
|
167 |
+
Vientiane
|
168 |
+
Wellington
|
169 |
+
|
170 |
+
The above listing has been
|
171 |
+
reviewed in the FE Division.
|
172 |
+
|
173 |
+
себ
|
174 |
+
|
175 |
+
Distribution For
|
176 |
+
Book Dispatch No. 4726
|
177 |
+
|
178 |
+
NE Division
|
179 |
+
Aden
|
180 |
+
Amman
|
181 |
+
Ankara
|
182 |
+
Baghdad
|
183 |
+
Beirut
|
184 |
+
Cairo
|
185 |
+
Colombo
|
186 |
+
Damascus
|
187 |
+
Jidda
|
188 |
+
Kabul
|
189 |
+
Karachi
|
190 |
+
Kathmandu
|
191 |
+
Kuwait
|
192 |
+
New Delhi
|
193 |
+
Tehran
|
194 |
+
|
195 |
+
The above listing has been
|
196 |
+
reviewed in the NE Division.
|
197 |
+
|
198 |
+
WE Division
|
199 |
+
Brussels
|
200 |
+
Copenhagen
|
201 |
+
The Hague
|
202 |
+
Helsinki
|
203 |
+
Lisbon
|
204 |
+
London
|
205 |
+
Luxembourg
|
206 |
+
Madrid
|
207 |
+
Oslo
|
208 |
+
Ottawa
|
209 |
+
Paris
|
210 |
+
Paris/LCPIPIT
|
211 |
+
Reykjavik
|
212 |
+
Rome
|
213 |
+
Stockholm
|
214 |
+
|
215 |
+
The above listing has been
|
216 |
+
reviewed in the WE Division.
|
217 |
+
|
218 |
+
-2-
|
219 |
+
|
220 |
+
Distribution For
|
221 |
+
Book Dispatch No. 4726
|
222 |
+
|
223 |
+
WH Division
|
224 |
+
Asuncion
|
225 |
+
Bogota
|
226 |
+
Buenos Aires
|
227 |
+
Caracas
|
228 |
+
Georgetown
|
229 |
+
Guatemala City
|
230 |
+
Kingston
|
231 |
+
La Paz
|
232 |
+
Lima
|
233 |
+
Managua
|
234 |
+
Mexico City
|
235 |
+
Montevideo
|
236 |
+
Panama City
|
237 |
+
Paramaribo
|
238 |
+
Port-au-Prince
|
239 |
+
Port of Spain
|
240 |
+
Quito
|
241 |
+
Rio de Janeiro
|
242 |
+
San Jose
|
243 |
+
San Juan
|
244 |
+
San Salvador
|
245 |
+
Santiago
|
246 |
+
Santo Domingo
|
247 |
+
Tegucigalpa
|
248 |
+
|
249 |
+
The above listing has been
|
250 |
+
reviewed in the WH Division.
|
251 |
+
|
252 |
+
-3-
|
253 |
+
|
254 |
+
Headquarters Distribution for
|
255 |
+
Book Dispatch No. 4726
|
256 |
+
|
257 |
+
2 DDP
|
258 |
+
1 ADDP
|
259 |
+
1 C/OPSER
|
260 |
+
1 C/TSD
|
261 |
+
1 C/CA
|
262 |
+
1 C/CCS
|
263 |
+
1 C/SOD
|
264 |
+
1 C/CI
|
265 |
+
1 C/FI
|
266 |
+
|
267 |
+
2 C/AF
|
268 |
+
1 C/AF/1
|
269 |
+
1 C/AF/2
|
270 |
+
1 C/AF/3
|
271 |
+
1 C/AF/4
|
272 |
+
1 C/AF/5
|
273 |
+
1 C/AF/6
|
274 |
+
|
275 |
+
2 C/EE
|
276 |
+
1 C/EE/G
|
277 |
+
1 C/EE/K
|
278 |
+
1 C/EE/SA
|
279 |
+
|
280 |
+
2 C/FE
|
281 |
+
1 C/FE/CH
|
282 |
+
1 C/FE/HULA
|
283 |
+
1 C/FE/JKO
|
284 |
+
1 C/FE/PMI
|
285 |
+
1 C/FE/TBL
|
286 |
+
1 C/FE/VNC
|
287 |
+
|
288 |
+
2 C/NE
|
289 |
+
1 C/NE/1
|
290 |
+
1 DC/NE/AA
|
291 |
+
1 C/NE/4
|
292 |
+
1 C/NE/5
|
293 |
+
1 C/NE/6
|
294 |
+
|
295 |
+
2 C/WE
|
296 |
+
1 C/WE/1
|
297 |
+
1 C/WE/2
|
298 |
+
1 C/WE/3
|
299 |
+
1 C/WE/4
|
300 |
+
1 C/WE/5
|
301 |
+
1 C/WE/BC
|
302 |
+
|
303 |
+
2 C/WH
|
304 |
+
1 C/WH/1
|
305 |
+
1 C/WH/2
|
306 |
+
1 C/WH/3
|
307 |
+
1 C/WH/4
|
308 |
+
1 C/WH/5
|
309 |
+
1 WH/COPS
|
310 |
+
1 WH/POA
|
311 |
+
1 WH/POB
|
312 |
+
1 WH/Plans
|
313 |
+
|
314 |
+
2 CI/R&A
|
315 |
+
1 CI/LIA
|
316 |
+
1 CI/OPS/AF
|
317 |
+
1 CI/OPS/EE
|
318 |
+
1 CI/OPS/FE
|
319 |
+
1 CI/OPS/NE
|
320 |
+
1 CI/OPS/SS
|
321 |
+
1 CI/OPS/WE
|
322 |
+
1 CI/OPS/WH
|
323 |
+
|
324 |
+
1 RID
|
325 |
+
|
326 |
+
Originated by: Chief, CI/R&A, Ext. 7468/23 December 1964
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10009-10021.md
ADDED
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
2 |
+
|
3 |
+
SECRET
|
4 |
+
|
5 |
+
FIELD DISTRIBUTION - BD #5847
|
6 |
+
|
7 |
+
AF DIVISION
|
8 |
+
Johannesburg
|
9 |
+
Lagos
|
10 |
+
Nairobi
|
11 |
+
Pretoria
|
12 |
+
Rabat
|
13 |
+
Salisbury
|
14 |
+
|
15 |
+
EUR DIVISION
|
16 |
+
Barcelona
|
17 |
+
Berlin
|
18 |
+
Bern
|
19 |
+
Bonn
|
20 |
+
Brussels
|
21 |
+
Copenhagen
|
22 |
+
Geneva
|
23 |
+
The Hague
|
24 |
+
Hamburg
|
25 |
+
Helsinki
|
26 |
+
Lisbon
|
27 |
+
London
|
28 |
+
Madrid
|
29 |
+
Milan
|
30 |
+
Munich Liaison Base
|
31 |
+
Munich Ops. Base (Laurion)
|
32 |
+
Oslo
|
33 |
+
Ottawa
|
34 |
+
Paris
|
35 |
+
LCPIPIT
|
36 |
+
Rome
|
37 |
+
Salzburg
|
38 |
+
Stockholm
|
39 |
+
Vienna
|
40 |
+
Zurich
|
41 |
+
|
42 |
+
NB DIVISION
|
43 |
+
Ankara
|
44 |
+
Athens
|
45 |
+
Beirut
|
46 |
+
Calcutta
|
47 |
+
Colombo
|
48 |
+
Istanbul
|
49 |
+
New Delhi
|
50 |
+
Rawalpindi
|
51 |
+
Teheren
|
52 |
+
|
53 |
+
FE DIVISION
|
54 |
+
Bangkok
|
55 |
+
Djakarta
|
56 |
+
Hong Kong
|
57 |
+
Honolulu
|
58 |
+
Kuala Lumpur
|
59 |
+
Kuching
|
60 |
+
Manila
|
61 |
+
Medan
|
62 |
+
Melbourne
|
63 |
+
Okinawa
|
64 |
+
Rangoon
|
65 |
+
Saigon
|
66 |
+
Seoul
|
67 |
+
Singapore
|
68 |
+
Taipei
|
69 |
+
Tokyo
|
70 |
+
Vientiane
|
71 |
+
Surabaya
|
72 |
+
Wellington
|
73 |
+
|
74 |
+
WH DIVISION
|
75 |
+
Asuncion
|
76 |
+
Bogota
|
77 |
+
Brasilia
|
78 |
+
Buenos Aires
|
79 |
+
Caracas
|
80 |
+
Georgetown
|
81 |
+
Guatemala City
|
82 |
+
Guayaquil
|
83 |
+
JMWAVE
|
84 |
+
Kingston
|
85 |
+
La Paz
|
86 |
+
Lima
|
87 |
+
Managua
|
88 |
+
Mexico City
|
89 |
+
Monterrey
|
90 |
+
Montevideo
|
91 |
+
Norfolk (REPLANT)
|
92 |
+
Panama City
|
93 |
+
Port au Prince
|
94 |
+
Porto Alegre
|
95 |
+
Quito
|
96 |
+
Recife
|
97 |
+
Rio de Janerio
|
98 |
+
San Jose
|
99 |
+
San Salvador
|
100 |
+
Santiago
|
101 |
+
Santiago de los Caballeros
|
102 |
+
Santo Domingo
|
103 |
+
Sao Paulo
|
104 |
+
Tegucigalpa
|
105 |
+
|
106 |
+
SECRET
|
107 |
+
|
108 |
+
HQS DISTRIBUTION - BD #5847
|
109 |
+
|
110 |
+
CA STAFF
|
111 |
+
DC/CA
|
112 |
+
CA/COPS
|
113 |
+
CA/PROP
|
114 |
+
CA/LO
|
115 |
+
CA/B1
|
116 |
+
CA/B2
|
117 |
+
CA/B3
|
118 |
+
CA/B4
|
119 |
+
CA/B5
|
120 |
+
|
121 |
+
AF/COPS/CA
|
122 |
+
AF/1
|
123 |
+
AF/2
|
124 |
+
AF/3
|
125 |
+
AF/4
|
126 |
+
AF/5
|
127 |
+
AF/6
|
128 |
+
|
129 |
+
FE/CA 14
|
130 |
+
C/CO/CA
|
131 |
+
|
132 |
+
SB/CA
|
133 |
+
|
134 |
+
DO/CA 3
|
135 |
+
|
136 |
+
CI/R&A 10
|
137 |
+
|
138 |
+
EUR DIVISION
|
139 |
+
E/CA
|
140 |
+
E/SC
|
141 |
+
E/BNL
|
142 |
+
E/F
|
143 |
+
E/I
|
144 |
+
E/IB
|
145 |
+
E/G
|
146 |
+
E/AS
|
147 |
+
E/BC
|
148 |
+
|
149 |
+
NE DIVISION
|
150 |
+
NE/COPS
|
151 |
+
NE/GTI/G
|
152 |
+
NE/GTI/T
|
153 |
+
NE/GTI/I
|
154 |
+
NEAA/I
|
155 |
+
NEAA/AP
|
156 |
+
NEAA/S&L
|
157 |
+
NESA/RE
|
158 |
+
NESA/C&N
|
159 |
+
NESA/I
|
160 |
+
NESA/P
|
161 |
+
|
162 |
+
WH DIVISION
|
163 |
+
WH/CA
|
164 |
+
WH/C
|
165 |
+
WH/C/CA
|
166 |
+
WH/1
|
167 |
+
WH/1/Mexico
|
168 |
+
WH/2
|
169 |
+
WH/2/G
|
170 |
+
WH/2/P
|
171 |
+
WH/H/S
|
172 |
+
WH/2/CR/N
|
173 |
+
WH/3
|
174 |
+
WH/3/B
|
175 |
+
WH/3/CO
|
176 |
+
WH/3/E
|
177 |
+
WH/3/P
|
178 |
+
WH/3/V
|
179 |
+
WH/4
|
180 |
+
WH/4/AR
|
181 |
+
WH/4/CH
|
182 |
+
WH/4/P/U
|
183 |
+
WH/5
|
184 |
+
WH/5/Brasil
|
185 |
+
WH/6
|
186 |
+
WH/7
|
187 |
+
WH/7/HT
|
188 |
+
WH/7/GU
|
189 |
+
WH/7/DR
|
190 |
+
WH/7/JTS
|
191 |
+
|
192 |
+
SECRET
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10009-10222.md
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
104-10009-10222
|
2 |
+
2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
3 |
+
|
4 |
+
SECRET
|
5 |
+
|
6 |
+
DD/P8:4635/1
|
7 |
+
|
8 |
+
26 NOV 1968
|
9 |
+
|
10 |
+
Sir Charles C. F. Spry
|
11 |
+
Director General
|
12 |
+
Australian Security Intelligence Organization
|
13 |
+
G. P. O. Box 510583
|
14 |
+
Melbourne
|
15 |
+
|
16 |
+
Dear Charles,
|
17 |
+
|
18 |
+
Thank you for your letter of 15 October
|
19 |
+
recommending against the declassification of
|
20 |
+
Warren Commission document CD-971. I might
|
21 |
+
mention that our inquiry to you in August (1968)
|
22 |
+
was in anticipation of further pressure for the
|
23 |
+
release of Warren Commission papers, a pressure
|
24 |
+
which has not materialized. Accordingly, there is
|
25 |
+
not, at the present time, any intention to release
|
26 |
+
CD-971.
|
27 |
+
|
28 |
+
Should the question be raised at some future
|
29 |
+
time, the points made by you in your letter provide
|
30 |
+
every reason to keep the document out of the
|
31 |
+
public domain.
|
32 |
+
|
33 |
+
With kindest regards,
|
34 |
+
|
35 |
+
Sincerely,
|
36 |
+
/s/ Richard Helms
|
37 |
+
|
38 |
+
Richard Helms
|
39 |
+
Director
|
40 |
+
|
41 |
+
Document Number 1042-947c
|
42 |
+
for FOIA Review on SEP 1976
|
43 |
+
|
44 |
+
cc: DDCI
|
45 |
+
|
46 |
+
Signature Recommended:
|
47 |
+
|
48 |
+
Deputy Director for Plans
|
49 |
+
DDP/FE/PMI/AN/Amos Taylor, Jr. (X 5502):aib (25 November 1968)
|
50 |
+
5681
|
51 |
+
|
52 |
+
Distribution:
|
53 |
+
Orig - Addee
|
54 |
+
1 - ADDP 2 - DCI
|
55 |
+
1 - CPE 1 - DDCI
|
56 |
+
1 - PMI 2 - DDP
|
57 |
+
1 - PMI/AN
|
58 |
+
21 NOV 1968
|
59 |
+
Date
|
60 |
+
|
61 |
+
SECRET
|
62 |
+
|
63 |
+
CORRES
|
64 |
+
RELATING TO
|
65 |
+
THIS-
|
66 |
+
INCLUDING
|
67 |
+
NAVYS OK
|
68 |
+
OF 27 June
|
69 |
+
|
70 |
+
FILE
|
71 |
+
MAIN
|
72 |
+
FILE
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10012-10022.md
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
2 |
+
|
3 |
+
SECRET
|
4 |
+
|
5 |
+
21 MAY
|
6 |
+
1982
|
7 |
+
US/82/71
|
8 |
+
|
9 |
+
Dear Anthony,
|
10 |
+
|
11 |
+
Regarding your letter 6/705 of 10 May 1982, our
|
12 |
+
records indicate that Valeriy Vladimirovich Kostikov
|
13 |
+
traveled to Mexico, France, Spain, the U.S. and Cuba
|
14 |
+
during the period 1959-61. In 1961, he was assigned
|
15 |
+
permanently to Mexico City as a consular officer and
|
16 |
+
served there until August 1965. He was variously
|
17 |
+
described as a translator, vice-consul, and attache.
|
18 |
+
During this tour he attempted to cultivate a U.S.
|
19 |
+
Government employee assigned to our embassy in Mexico
|
20 |
+
City.
|
21 |
+
|
22 |
+
In September/October 1963, Lee Harvey Oswald
|
23 |
+
approached the Soviet Embassy in Mexico City in an attempt
|
24 |
+
to get a visa allowing him to return to the USSR.
|
25 |
+
Kostikov, as a consular officer, handled this visa
|
26 |
+
request. We have no information which indicates any
|
27 |
+
relationship between these individuals other than for the
|
28 |
+
purpose of Oswald's making his visa request.
|
29 |
+
|
30 |
+
Kostikov returned to Mexico City for a second tour of
|
31 |
+
duty in July 1968. During this tour he was again assigned
|
32 |
+
to the consular section and was a second secretary. It
|
33 |
+
appeared that he was tasked with following the activities
|
34 |
+
of the Central American communist parties and left-wing
|
35 |
+
groups, and he met often with members of these groups,
|
36 |
+
reportedly providing them with funds and technical
|
37 |
+
guidance. In July/August 1969, Kostikov made an unusual
|
38 |
+
TDY trip to Moscow lasting three weeks. (His family
|
39 |
+
remained in Mexico.) In July 1970 he made a four-day trip
|
40 |
+
to Havana.
|
41 |
+
|
42 |
+
Kostikov's tour in Mexico ended unexpectedly in
|
43 |
+
September 1971. Our information indicated that he was
|
44 |
+
not due to leave for another three to four months, and at
|
45 |
+
the time of his departure, there was some speculation that
|
46 |
+
the suddenness of his departure was due to the fact that
|
47 |
+
he was known to Lyalin.
|
48 |
+
|
49 |
+
CROSS FILE COPY FOR
|
50 |
+
201-289248
|
51 |
+
DO NOT DESTROY
|
52 |
+
|
53 |
+
RECORD COPY
|
54 |
+
|
55 |
+
SECRET
|
56 |
+
|
57 |
+
XAE09222
|
58 |
+
21MAY 82
|
59 |
+
100-2-95
|
60 |
+
|
61 |
+
While in Mexico he was considered by some to be the
|
62 |
+
most effective and dangerous of intelligence officers in
|
63 |
+
Mexico. He has been described as being without morals,
|
64 |
+
education, and manners. Shortly after his arrival in
|
65 |
+
Mexico in 1968, he was arrested in front of a house of
|
66 |
+
prostitution after becoming involved in a fist fight with
|
67 |
+
some locals. It appears this incident did not affect his
|
68 |
+
position in Mexico City, despite the fact that it
|
69 |
+
received a good deal of press coverage.
|
70 |
+
|
71 |
+
We are aware only that Kostikov arrived in Beirut in
|
72 |
+
June 1978. We are unable to confirm his presence there
|
73 |
+
now.
|
74 |
+
|
75 |
+
Although our file indicates that Kostikov may have
|
76 |
+
been a member of Department 13 (Executive Action)
|
77 |
+
(Department V's predecessor), we have been unable to
|
78 |
+
confirm this. Also, to the best of our knowledge the KGB
|
79 |
+
has not engaged in such executive action since 1959.
|
80 |
+
|
81 |
+
Sincerely,
|
82 |
+
|
83 |
+
/s/ David
|
84 |
+
|
85 |
+
David H. Blee
|
86 |
+
|
87 |
+
Mr. Anthony C. M. DeVere
|
88 |
+
|
89 |
+
PHOTO ATTACHED
|
90 |
+
|
91 |
+
DDO/CI/RA/Joan Paxson (21 May 1982)
|
92 |
+
|
93 |
+
DISTRIBUTION:
|
94 |
+
Orig & 1 - Adse
|
95 |
+
1 - CI/RA Chrono
|
96 |
+
1 - 100-2-95
|
97 |
+
1 - Reading Board
|
98 |
+
1 - Paxson
|
99 |
+
|
100 |
+
SECRET
|
101 |
+
|
102 |
+
100-2-95
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10012-10024.md
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
104-10012-10024 2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
2 |
+
|
3 |
+
6/705
|
4 |
+
10 May 1982
|
5 |
+
|
6 |
+
Dear David,
|
7 |
+
|
8 |
+
VALERIY VLADIMIROVICH KOSTIKOV
|
9 |
+
|
10 |
+
1. Please refer to our conversation of 6 May. KOSTIKOV, born 17 March 1933, Moscow, was posted to Beirut in 1978 as 1st Secretary and may still be there. He is identified KGB and served in Mexico City from 1961-71. There is a reference to him on page 307 of BARRON's KGB which suggests that he may have been Department V. We do not appear to have asked LYALIN about him, and are now doing so.
|
11 |
+
|
12 |
+
2. We also note that EPSTEIN in "Legend" claims that according to a CIA telecheck KOSTIKOV was Lee Harvey OSWALD'S KGB case officer in Mexico City. According to BARRON (page 335) OSWALD was in Mexico between September and November 1963 and was seeking to obtain a Soviet visa. There was certainly a KGB interest in OSWALD, although according to NOSENKO this was defensive.
|
13 |
+
|
14 |
+
3. The reason for our current interest in KOSTIKOV will be obvious. As you are aware, our Embassy in Beirut, in common with other Western Missions, has been subject to threats and violence in recent months, and in view of earlier hostile attentions from the KGB, we have been reviewing our records of KGB staff in the area who might have been involved in promoting strong-arm tactics.
|
15 |
+
|
16 |
+
4. We would be grateful for your views as to whether the KGB are likely to be behind any of the recent incidents (possibly through the Syrians) and for any information on KOSTIKOV and his activities in Mexico and in Beirut. In particular, what are your comments on the OSWALD story; can you confirm that KOSTIKOV is still in Beirut; is there anyone else in Beirut or Damascus whose trace record suggests an Active Measures role, or worse?
|
17 |
+
|
18 |
+
5. We should be grateful for an early reply and as I said on 6 May will treat anything you can tell us on a strictly Service to Service basis.
|
19 |
+
|
20 |
+
CROSS FILE COPY FOR
|
21 |
+
201-289248
|
22 |
+
|
23 |
+
DO NOT DESTROY
|
24 |
+
|
25 |
+
Yours ever
|
26 |
+
|
27 |
+
A C M de Vere
|
28 |
+
|
29 |
+
Form 547a Processed
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10012-10035.md
ADDED
@@ -0,0 +1,208 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# 2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
2 |
+
|
3 |
+
1 UNCLASSIFIED
|
4 |
+
INTERNAL USE ONLY
|
5 |
+
CONFIDENTIAL
|
6 |
+
SECRET
|
7 |
+
|
8 |
+
ROUTING AND RECORD SHEET
|
9 |
+
|
10 |
+
SUBJECT: (Optional)
|
11 |
+
|
12 |
+
FROM: E/BC
|
13 |
+
4C 20 Hqs?
|
14 |
+
|
15 |
+
EXTENSION NO
|
16 |
+
1413
|
17 |
+
7220
|
18 |
+
|
19 |
+
DATE
|
20 |
+
5 APR 1978
|
21 |
+
|
22 |
+
TO: (Officer designation, room number, and building)
|
23 |
+
|
24 |
+
DATE
|
25 |
+
OFFICER'S INITIALS
|
26 |
+
RECEIVED
|
27 |
+
FORWARDED
|
28 |
+
COMMENTS (Number each comment to show from whom to whom. Draw a line across column, after each comment.)
|
29 |
+
|
30 |
+
1. CilRTA
|
31 |
+
2. Hausman APR 1978 ch
|
32 |
+
3. Rum Holmes
|
33 |
+
4. 3D57
|
34 |
+
5.
|
35 |
+
6.
|
36 |
+
7.
|
37 |
+
8.
|
38 |
+
9.
|
39 |
+
10.
|
40 |
+
This is the ACTION/INFO copy of a communication received on from MI-6 in Washington.
|
41 |
+
|
42 |
+
Another copy is being held in E/BC.
|
43 |
+
|
44 |
+
Any reply should be directed to E/BC for forwarding to Liaison.
|
45 |
+
|
46 |
+
Processing by IP is to be determined by
|
47 |
+
|
48 |
+
Coordination with E/BC is required prior to any dissemination of this information outside the DDO.
|
49 |
+
|
50 |
+
NB: Richard A. SPRAGUE, Chief Counsel and Director of HSCA, saw a copy of attached document... See his attached letter to Sergyj CZORNONOH, 04 December 1976.
|
51 |
+
|
52 |
+
RBH
|
53 |
+
11.
|
54 |
+
12.
|
55 |
+
13.
|
56 |
+
14.
|
57 |
+
15.
|
58 |
+
|
59 |
+
FORM 610 USE PREVIOUS EDITIONS
|
60 |
+
SECRET
|
61 |
+
CONFIDENTIAL
|
62 |
+
INTERNAL USE ONLY
|
63 |
+
UNCLASSIFIED
|
64 |
+
|
65 |
+
CONFIDENTIAL
|
66 |
+
|
67 |
+
Our ref: GEN 1
|
68 |
+
|
69 |
+
Dear Art,
|
70 |
+
|
71 |
+
30 March 1978
|
72 |
+
|
73 |
+
Please find attached correspondence received from one Sergyj CZORNONOH who claims that he provided information about Lee Harvey OSWALD to the American Vice Consul (presumably Tom Blackshear) in Sofia, Bulgaria, in August 1963.
|
74 |
+
|
75 |
+
2. I have sent copies of these letters to the FBI and to my Head Office in London.
|
76 |
+
|
77 |
+
Mr A H Stimson
|
78 |
+
|
79 |
+
Enc.
|
80 |
+
|
81 |
+
DH Jones for GML Blackburne-Kan
|
82 |
+
|
83 |
+
CONFIDENTIAL
|
84 |
+
|
85 |
+
SERGYJ. CZORNONOH
|
86 |
+
1106-11TH STREET
|
87 |
+
SACRAMENTO CALIFORNIA
|
88 |
+
95814
|
89 |
+
|
90 |
+
M. Wall
|
91 |
+
|
92 |
+
TO BRITISH EMBASSY
|
93 |
+
3100 MASSACHUSETTS AVE, N. W.
|
94 |
+
WASHINGTON, D. C.
|
95 |
+
|
96 |
+
RETURN RECEIPT REQUESTED
|
97 |
+
REGISTERED NO.257254
|
98 |
+
|
99 |
+
SERGYJ CZORNONDH
|
100 |
+
1106-11TH STREET
|
101 |
+
SACRAMENTO, CALIFORNIA, 95814
|
102 |
+
|
103 |
+
MARCH 15, 1978.
|
104 |
+
|
105 |
+
TO BRITISH AMBASSADOR
|
106 |
+
BRITISH EMBASSY
|
107 |
+
3100 MASSACHUSETTS AVE, N. W.
|
108 |
+
WASHINGTON, DC.
|
109 |
+
|
110 |
+
DEAR SIR.
|
111 |
+
|
112 |
+
I WROTE LETTER ON FEBRUARY 15, 1978 TO MR. JAMES CALLAGHAN PRIME MINISTER I ENCLOSED REGISTERED MAIL NO. 251067.
|
113 |
+
|
114 |
+
ON JULY 18, 1963 I WAS IN LONDON ENGLAND AT THE AIRPORT IMMIGRATION OFFICER NO. 175 I HAD NO VISA IMMIGRATION PLACE ME UNDER HOUSE ARREST, MR. SMITH IN POLICE UNIFORM SECRET SERVICE BROUGHT ME STEAK DINNER AND POLICE OFFICER INTERROGATED ME, HE ASKED ME WHAT THE EMBASSY OF US.S.R. SAY YOU HEARD IN VIENNA, AUSTRIA, I SAID I HAVE HEARD THAT ONE AMERICAN DEFECTOR (MR. LEE HARVEY OSWALD) TO RUSSIA AND HE RETURNED TO UNITED STATES OF AMERICA THIS MAN HE PREPARING TO KILL TO ASSASSINATE PRESIDENT JOHN F. KENNEDY, MR. SMITH POLICE OFFICER ASKED ME DO YOU KNOW HIS NAME, I SAID HIS NAME SOHT ONTO TIME WAS PUBLISHED ONE TIME IN NEWS PAPER IN WASHINGTON POST, MR. SMITH POLICE OFFICER SAID
|
115 |
+
|
116 |
+
I DO SEARCHING FOR THIS FILE IN BRITISH POLICE BRITISH INTELLIGENCE AND BRA IMMIGRATION, JASKING YOUR EMBASSY TO HELP TO FIND THE TRUTH AND I ASK YOUR GOVERNMENT TO FORWARD My RECORD CE JULY 181 1963 TO PRESIDENT JIMMY CARTER AND SENATOR DANIEL K. NOUYE CHAM 21. S. SENATE SELECT COMMITTEE ON IN 11 GENCE I ENCLOSE HIS Copy LETTER TO ALSO I ENCLOSE you copy LETTER I JANT ON FEBRUARY 17, 1978 TO RUSSIAN AMMASSA YOUR JUSTICE ALWAYS WILL BE APPLIA MY INCOMING MAIL iS CONTROL BY FIBI AGENTS SOME OF THE MAIL IDENT GET NOT FORWARD TO ME FIBI, Suppress My INFORMATION AND TORTURE MED DRUG RESPECTFULLY YOURS "21.S. PASSPORT NO, DO 2.7000 Sergyj
|
117 |
+
|
118 |
+
copy. 10
|
119 |
+
BRITISH AMBASSADOR
|
120 |
+
|
121 |
+
Sergyj Czornonoh
|
122 |
+
1106- 11th Street
|
123 |
+
Sacramento, California 95814
|
124 |
+
|
125 |
+
To Russian Ambassador
|
126 |
+
Embassy of U.S.S.R.
|
127 |
+
1125 - 16th Street
|
128 |
+
Washington, D. C.
|
129 |
+
|
130 |
+
Dear Sir:
|
131 |
+
|
132 |
+
This is retyped letter from hand written
|
133 |
+
|
134 |
+
Mr. Wasilev Consul gave me order to transmit this information to U. S. Government, on August 9, 1963 in Sofia, Bulgaria. Mr. Wasilev, Consul of Embassy of U.S.S.R., gave me this information about Mr. Lee Harvey Oswald on August 14, 1963. Mrs. Besera Asenova, girl friend of Russian Consul came to my room and repeated that Mr. Lee Harvey Oswald is assassin. He will kill President Kennedy.
|
135 |
+
|
136 |
+
On August 15, 1963 in Sofia, Bulgaria, at the airport in embassy car, I told to Mr. Blackshire, American Vice Consul, that Mr. Lee Harvey Oswald is assissin. He has a weapon or has ordered one. Mr. Blackshire said it seems like he will kill someone. I said that Mr. Lee H. Oswald is preparing to kill President of the United States, John F. Kennedy. Mr. Blackshire said where will it happen. I said they (right wing) will invite President, criticize him in the newspaper, then kill him. Mr. Blackshire told me he will give the telegram to Department of State and he gave me the address where to report.
|
137 |
+
|
138 |
+
At 9 a.m. on August 19, 1963 in Washington, D. C., I went to see (Mr. Kippingan). Director of Special Counselor Service Department of State at 1901 Pennsylvania Avenue-11th floor. I told the Director that I have information about President Kennedy. The Director said do not mention name of President Kennedy, only respond to the questions. The Director said tell us what will happen to Mr. Lee Harvey Oswald then. I said Mr. Lee H. Oswald will be killed after kill Kennedy. I said I will take the truth drug to tell the truth. Director tell us who else get killed in this country. I said as I heard, that Dr. Martin Luther King, Jr. will be killed. Who will kill Dr. King, Jr. Negro leader? I said a man who is in prison at this time. (Mr. James Earl Ray was in prison at that time.) Director asked where assassination will happen. I said in Dallas, Texas. Director said if someone gave this information here I would expel the man. Director did call on F.B.I. agents after F.B.I. use anesthesia gas to freeze me to drub me to keep amnesia.
|
139 |
+
|
140 |
+
I told Director Department of State that Mr. Lee Harvey Oswald have a weapon. Go see him. Director told me you too can have weapon--so what if Oswald got weapon.
|
141 |
+
|
142 |
+
Sincerely,
|
143 |
+
|
144 |
+
U.S House of Representatives Select Committee on Assassinations told me to write letter to Embassy in early 1977.
|
145 |
+
|
146 |
+
Sergyj Czornonoh
|
147 |
+
Regis Hotel
|
148 |
+
1106 11th Street
|
149 |
+
Sacramento, CA 95814
|
150 |
+
|
151 |
+
GITY MANAGEAS
|
152 |
+
ABOUT HUMAN RIGHTS
|
153 |
+
BRITISH EMBASSY
|
154 |
+
|
155 |
+
February 6, 1978
|
156 |
+
|
157 |
+
Mr. John M. Price
|
158 |
+
District Attorney
|
159 |
+
Sacramento, California
|
160 |
+
|
161 |
+
Dear Mr. Price:
|
162 |
+
|
163 |
+
This is a retyped letter. I visited Mr. Ferry, Deputy District Attorney, on August 16, 1977. I told in the office that F.B.I. agents and Secret Service use police department to harass me. Police department do... supply pencil of anesthesia gas to the manager of the building I live. The manager door use certain people, to freeze me by anesthesia gas - then push drugs, poison in my mouth to torture me - to take my sleep away - or bleed by rectal and they use many other chemicals to brainwash me to use me in political assassination which I refused. On January 20, 1976 in Sacramento on 8th and I Streets, man came to me from police or post office, U.S. Department of Justice and freeze me by gas and told me to take gun, pistol and we will tell you where to go to shoot - to kill - Mr. Sargent Shriver. I refused. Manager, Mr. Sisel, of Marshall Hotel, call on the man to tell me this on the street. In February 1976, police intelligence told me that assassination will not happen here. How about to move to Maryland state.
|
164 |
+
|
165 |
+
In this letter I ask you to get report from Dr. Frederick S. Baker, M.D. colon and rectal surgery on January 31, 1978. His phone – 452-4095. I do bleed today very much and I am weak, In this letter I ask you to give re- strain order or respond to me what could be done. The right wing in America made record to use me in assassination. I refuse. I am human and I like to be treated as human. Police put frame up on me - just to take advantages on me. Police use lie, police use mental case to take advantages on me and tell me that right wing do use such people like me. To prove I enclose copy mid- night June 14, 1976. Also I enclose copy letter I sent to Mr. Ted Sheedy, Supervisor, on January 26, 1978 and copy of his reply to me.
|
166 |
+
|
167 |
+
Please respond to me. Thank you.
|
168 |
+
|
169 |
+
Very truly yours
|
170 |
+
|
171 |
+
Sergyj. Czornonoh
|
172 |
+
|
173 |
+
Mr. Sargent Shriver was run for President in 1976.
|
174 |
+
|
175 |
+
Legal Center
|
176 |
+
For The Disabled
|
177 |
+
|
178 |
+
1722 J STREET, SUITE 19 SACRAMENTO, CA 95814
|
179 |
+
Telephone: 446-4851
|
180 |
+
|
181 |
+
March, 1978
|
182 |
+
|
183 |
+
Sergyj Czornonoh
|
184 |
+
1106 11th Street
|
185 |
+
Sacramento, CA 95814
|
186 |
+
|
187 |
+
Dear Mr. Czornonoh:
|
188 |
+
|
189 |
+
This is to acknowledge receipt of your letter regarding difficulties you have encountered with the police and the FBI.
|
190 |
+
|
191 |
+
In the event that there is legal action taken by the police or the FBI to institutionalize you this office will provide you with legal representation.
|
192 |
+
|
193 |
+
If you have any further legal problems please contact this office.
|
194 |
+
|
195 |
+
Sincerely,
|
196 |
+
|
197 |
+
LESLIE KAY
|
198 |
+
Paralegal
|
199 |
+
|
200 |
+
CATHERINE HUGHES
|
201 |
+
Staff Attorney
|
202 |
+
LK: ab
|
203 |
+
|
204 |
+
REGISTERED NO 2.51067
|
205 |
+
FROM 1106801124 95814
|
206 |
+
TO MR. JAMES CALLAGHAN
|
207 |
+
SF Wen la OFFICE OF MINISTRY
|
208 |
+
LONDON ENGLAND
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10012-10076.md
ADDED
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
13-00000
|
2 |
+
|
3 |
+
FIELD DISTRIBUTION
|
4 |
+
|
5 |
+
A Division
|
6 |
+
WH Division
|
7 |
+
NE Division
|
8 |
+
DISTRIBUTION TO BD -
|
9 |
+
r
|
10 |
+
Abidjan
|
11 |
+
Asuncion
|
12 |
+
Amman
|
13 |
+
Accra
|
14 |
+
Fagota
|
15 |
+
Ankara 2
|
16 |
+
Addis Ababa
|
17 |
+
Erasilia
|
18 |
+
Athens 5
|
19 |
+
Апиете
|
20 |
+
Fenos Aires
|
21 |
+
Beirut 3
|
22 |
+
Bangal
|
23 |
+
Cazucas 2
|
24 |
+
Bombay
|
25 |
+
toncu
|
26 |
+
Georgetown
|
27 |
+
Calcutta
|
28 |
+
Dakar
|
29 |
+
Guatemala
|
30 |
+
Colombo
|
31 |
+
Ier at Salava
|
32 |
+
Quayaquil
|
33 |
+
Dacca
|
34 |
+
Kaipals
|
35 |
+
Kingstoc
|
36 |
+
Istanbul
|
37 |
+
Freetown
|
38 |
+
La Paz
|
39 |
+
Jerusalem
|
40 |
+
Khartoum
|
41 |
+
Lima
|
42 |
+
Jidda
|
43 |
+
Kiastasa
|
44 |
+
Keduaa
|
45 |
+
Mexico City 2
|
46 |
+
Kabul
|
47 |
+
Mutevideo
|
48 |
+
Karachi
|
49 |
+
Lagos
|
50 |
+
Рапяка
|
51 |
+
Katmandu
|
52 |
+
Lusaka
|
53 |
+
Forte Alegre
|
54 |
+
Kirwait
|
55 |
+
Mogadiscio
|
56 |
+
Av Spain
|
57 |
+
Lahore
|
58 |
+
Moarovia
|
59 |
+
Madras
|
60 |
+
CI/ICG
|
61 |
+
Nairobi
|
62 |
+
Recife
|
63 |
+
New Delhi
|
64 |
+
Rabat
|
65 |
+
Rio de Janeiro 2
|
66 |
+
Nicosia
|
67 |
+
Tripoli
|
68 |
+
San Jose
|
69 |
+
Rawalpindi
|
70 |
+
Yamade
|
71 |
+
Sau Salvador
|
72 |
+
Teheran
|
73 |
+
Santiago 2
|
74 |
+
|
75 |
+
Sento Domiαει
|
76 |
+
EUR Division
|
77 |
+
Ses Paulc
|
78 |
+
Berlin 3
|
79 |
+
Tegucigalpa
|
80 |
+
Bern
|
81 |
+
Madrid 2
|
82 |
+
Bona 5
|
83 |
+
Preseis
|
84 |
+
Copenhagen
|
85 |
+
Frankfurt
|
86 |
+
FE Divisi
|
87 |
+
|
88 |
+
Do agirak 3
|
89 |
+
karta
|
90 |
+
3
|
91 |
+
AF/2
|
92 |
+
Heleinkta
|
93 |
+
2
|
94 |
+
4
|
95 |
+
karta 2
|
96 |
+
Matid
|
97 |
+
2
|
98 |
+
TALA Lumpur
|
99 |
+
Munich betria) 3
|
100 |
+
Mars la
|
101 |
+
2
|
102 |
+
Me ibaurtu
|
103 |
+
Peru
|
104 |
+
kizawa
|
105 |
+
Pame
|
106 |
+
2
|
107 |
+
כם
|
108 |
+
stockholm
|
109 |
+
Sat 2
|
110 |
+
Sen
|
111 |
+
ogue 2
|
112 |
+
Singapora
|
113 |
+
Vine
|
114 |
+
Suracaye
|
115 |
+
Zurich
|
116 |
+
Taipei 2
|
117 |
+
Tokyo
|
118 |
+
2
|
119 |
+
Vientians
|
120 |
+
Wellington
|
121 |
+
BD 6614?
|
122 |
+
SB/Division
|
123 |
+
C/SB
|
124 |
+
SB/CA
|
125 |
+
SB/BR
|
126 |
+
SB/C
|
127 |
+
SB/YA
|
128 |
+
SB/P
|
129 |
+
SB/CI
|
130 |
+
|
131 |
+
WH/C/CA/PROP 2
|
132 |
+
WH/CA
|
133 |
+
|
134 |
+
WH/1,2,3,4,5
|
135 |
+
WH/7/JTS, CU
|
136 |
+
|
137 |
+
1-D/RR
|
138 |
+
2-DOCA
|
139 |
+
CI/FA
|
140 |
+
|
141 |
+
FBID/Weisa
|
142 |
+
VTR/SIC
|
143 |
+
OTR/Isolation Library
|
144 |
+
FL/8PG
|
145 |
+
MPS/PSC
|
146 |
+
|
147 |
+
CS Special Group Offic
|
148 |
+
INTERNAL DISTRIBUTION
|
149 |
+
AP/COP/CA
|
150 |
+
AP/1
|
151 |
+
C/CA - DC/CA
|
152 |
+
C/CA/PEG
|
153 |
+
AP/L
|
154 |
+
CA/EL 3
|
155 |
+
AF/5
|
156 |
+
08/53 3
|
157 |
+
CA/DA
|
158 |
+
AF/6-Ethiopia
|
159 |
+
40/80
|
160 |
+
C/EUR
|
161 |
+
E/ONE/CA
|
162 |
+
CA/FROF
|
163 |
+
E/G
|
164 |
+
8/A8
|
165 |
+
B/SC
|
166 |
+
E/BNE
|
167 |
+
E/BC
|
168 |
+
E/F
|
169 |
+
ق
|
170 |
+
1/2
|
171 |
+
E/LB
|
172 |
+
|
173 |
+
FE/CA 16
|
174 |
+
|
175 |
+
|
176 |
+
NE/SA/A
|
177 |
+
NE/GTA!!
|
178 |
+
NE/GES T
|
179 |
+
NF 'COPS
|
180 |
+
NEGA/I
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10012-10078.md
ADDED
@@ -0,0 +1,199 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
2 |
+
104-10012-10078
|
3 |
+
QUNCLASSIFIED
|
4 |
+
ONLY
|
5 |
+
ROUTING AND RECORD SHEET
|
6 |
+
ENTIAL
|
7 |
+
SECRET
|
8 |
+
SUBJECT: (Optional)
|
9 |
+
FROM:
|
10 |
+
Chief Far East Division
|
11 |
+
TO: (Officerdesignation, room number, and.
|
12 |
+
building)
|
13 |
+
EXTENSION NO.
|
14 |
+
FORWARDED
|
15 |
+
OFFICER'S
|
16 |
+
INITIALS:
|
17 |
+
DATE
|
18 |
+
20 Nov.68
|
19 |
+
COMMENTS (Number each comment to show from whom
|
20 |
+
to whom. Draw a line across column after each comment.)
|
21 |
+
DATE
|
22 |
+
RECEIVED
|
23 |
+
Chief CI Staff 27 NOV 1968
|
24 |
+
CIRA
|
25 |
+
Mr. Dooley
|
26 |
+
27 NOV 1968
|
27 |
+
boo
|
28 |
+
for file
|
29 |
+
Document Number
|
30 |
+
येद
|
31 |
+
1128-988
|
32 |
+
for FOIA Review on SEP 1976
|
33 |
+
201-289248
|
34 |
+
FORM
|
35 |
+
3-62
|
36 |
+
610
|
37 |
+
USE PREVIOUS
|
38 |
+
EDITIONS
|
39 |
+
SECRET
|
40 |
+
CONFIDENTIAL
|
41 |
+
INTERNAL
|
42 |
+
USE ONLY
|
43 |
+
UNCLASSIFIED
|
44 |
+
|
45 |
+
UNCLASSIFIEDERAL CO DENTIAL
|
46 |
+
SUBJECT: (Optional)
|
47 |
+
FROM: CIRAIRS
|
48 |
+
2323
|
49 |
+
TO: (Officer designation, room number, and
|
50 |
+
building)
|
51 |
+
1.
|
52 |
+
IP/AN
|
53 |
+
2.
|
54 |
+
3.
|
55 |
+
4.
|
56 |
+
5.
|
57 |
+
JP/EDI
|
58 |
+
6.
|
59 |
+
7.
|
60 |
+
8.
|
61 |
+
9.
|
62 |
+
10.
|
63 |
+
Document Number
|
64 |
+
for FOIA Review on
|
65 |
+
28/Flas
|
66 |
+
HP/RMS
|
67 |
+
12.
|
68 |
+
13.
|
69 |
+
ONLY
|
70 |
+
ROUTING AND RECORD SHEET
|
71 |
+
EXTENSION NO.
|
72 |
+
DATE
|
73 |
+
OFFICER'S
|
74 |
+
INITIALS
|
75 |
+
RECEIVED
|
76 |
+
FORWARDED
|
77 |
+
DATE
|
78 |
+
26 που. 68
|
79 |
+
XAAZ-35926
|
80 |
+
26 NOU 68-
|
81 |
+
SECRET
|
82 |
+
COMMENTS (Number each comment to show from whom
|
83 |
+
to whom. Draw a line across column after each comment.)
|
84 |
+
@ Please asijo
|
85 |
+
XAAZ # and
|
86 |
+
os pay & Of
|
87 |
+
1128-988
|
88 |
+
SEP 1976
|
89 |
+
MAY
|
90 |
+
1978
|
91 |
+
clamifs to
|
92 |
+
201-289748
|
93 |
+
26.
|
94 |
+
Date: 2 NOV 68)
|
95 |
+
Salgent
|
96 |
+
Covesperelerce Cotisan
|
97 |
+
0%
|
98 |
+
CIA and ASIO.
|
99 |
+
Re: release
|
100 |
+
of exftinatun ly
|
101 |
+
Woven Commessen
|
102 |
+
14.
|
103 |
+
15.
|
104 |
+
FORM
|
105 |
+
3-62
|
106 |
+
D
|
107 |
+
610
|
108 |
+
USE PREVIOUS
|
109 |
+
EDITIONS
|
110 |
+
SECRET
|
111 |
+
CONFIDENTIAL
|
112 |
+
INTERNAL
|
113 |
+
USE ONLY
|
114 |
+
UNCLASSIFIED
|
115 |
+
|
116 |
+
SECRET
|
117 |
+
20 NOV 1968
|
118 |
+
KEMORANDUM FOR: Director of Central Intelligence
|
119 |
+
VIA
|
120 |
+
SUBJECT
|
121 |
+
Deputy Director for Plane
|
122 |
+
304635
|
123 |
+
Executive Registry
|
124 |
+
68-516011
|
125 |
+
XAAZ-
|
126 |
+
35926
|
127 |
+
Letter for Direstor from Bir Charles Spry (ASIO)
|
128 |
+
1. Attached is a scaled letter fron Sir Charles Spry,
|
129 |
+
Director General of the Australian Security Intelligenco
|
130 |
+
Organization (who provided a copy of the letter to the Chief
|
131 |
+
of Station, Heibourne), and a suggested reply for your
|
132 |
+
signature.
|
133 |
+
2. Bir Charles' letter to you recommends again好家
|
134 |
+
doclassification of the Farrea Comaission document CD-971,
|
135 |
+
which refers to our investigation of anonymous telephone
|
136 |
+
calls to the Canberra Babassy before and after the
|
137 |
+
amcassination of President Kennedy.
|
138 |
+
3. I consider the points made by Bir Charles in his
|
139 |
+
letter to be valid and accordingly recommend against the
|
140 |
+
decisosification of CD-971 in the foreseeable fature
|
141 |
+
Staff concurs with this recommendation.
|
142 |
+
Document Number 1128-988
|
143 |
+
for FOLA Review on SEP 1976
|
144 |
+
4. Naison
|
145 |
+
William E. Nelson
|
146 |
+
of
|
147 |
+
K
|
148 |
+
P/ERI
|
149 |
+
Chief, Far East Division
|
150 |
+
Attachments, 5
|
151 |
+
130/900
|
152 |
+
A.
|
153 |
+
Letter from Sir Charles Spry
|
154 |
+
PROCARE FOR THAUNG
|
155 |
+
575 40. (2.3.4)
|
156 |
+
AVGAT REST, CODE
|
157 |
+
CABLE ICON (11)
|
158 |
+
(4)
|
159 |
+
B.
|
160 |
+
Letter Replying to Sir Charles Spry
|
161 |
+
P/FRES
|
162 |
+
FOR FILING
|
163 |
+
C. FAMA 5008, subject: Declassification of Warreh
|
164 |
+
Commission Document CD-971-
|
165 |
+
D.
|
166 |
+
Copy of CD-971
|
167 |
+
E. FAMW 3636, subject: Request for Release of Warren
|
168 |
+
Commission Document
|
169 |
+
20: DOCI
|
170 |
+
DDP/FE/PMI/AN: Amos Taylor, Jrl:arc (19) November 1968)
|
171 |
+
Distribution
|
172 |
+
Orig & 1
|
173 |
+
-
|
174 |
+
Addressee
|
175 |
+
1 DDCI
|
176 |
+
-
|
177 |
+
2
|
178 |
+
-
|
179 |
+
1
|
180 |
+
DDP
|
181 |
+
ADDP
|
182 |
+
RECORD COPY
|
183 |
+
-
|
184 |
+
1
|
185 |
+
1
|
186 |
+
1
|
187 |
+
-
|
188 |
+
1
|
189 |
+
-
|
190 |
+
GEODET
|
191 |
+
C/CI Staff
|
192 |
+
CFE
|
193 |
+
CFE/PMI
|
194 |
+
wanatic
|
195 |
+
...and
|
196 |
+
neslassification
|
197 |
+
CFE/PMI/AN
|
198 |
+
26 που 68
|
199 |
+
201-289248
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10012-10079.md
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
2 |
+
|
3 |
+
SECRET
|
4 |
+
|
5 |
+
68-2/60/a
|
6 |
+
RD/08-4635/
|
7 |
+
|
8 |
+
26 NOV 1968
|
9 |
+
|
10 |
+
FILE
|
11 |
+
|
12 |
+
Sir Charles C. F. Spry
|
13 |
+
Director General
|
14 |
+
Australian Security Intelligence Organization
|
15 |
+
G. P. O. Box 51058B
|
16 |
+
Melbourne
|
17 |
+
|
18 |
+
Dear Charles,
|
19 |
+
|
20 |
+
Thank you for your letter of 15 October
|
21 |
+
recommending against the declassification of
|
22 |
+
Warren Commission document CD-071. I might
|
23 |
+
mention that our inquiry to you in August (1968)
|
24 |
+
was in anticipation of further pressure for the
|
25 |
+
release of Warren Commission papers, a pressure
|
26 |
+
which has not materialized. Accordingly, there is
|
27 |
+
not, at the present time, any intention to release
|
28 |
+
CD-971.
|
29 |
+
|
30 |
+
Should the question be raised at some future
|
31 |
+
time, the points made by you in your letter provide
|
32 |
+
every reason to keep the document out of the
|
33 |
+
public domain.
|
34 |
+
|
35 |
+
With kindest regards,
|
36 |
+
|
37 |
+
Sincerely,
|
38 |
+
|
39 |
+
/s/ Richard Helms
|
40 |
+
|
41 |
+
Richard Helms
|
42 |
+
Director
|
43 |
+
|
44 |
+
cc: DDCI
|
45 |
+
|
46 |
+
Signature Recommended:
|
47 |
+
|
48 |
+
Deputy Director for Plans
|
49 |
+
|
50 |
+
Distribution:
|
51 |
+
Orig - Addee
|
52 |
+
1 - ADDP 2 - DCI
|
53 |
+
1 - CFE 1 - DDCI
|
54 |
+
1 - PMI 2 - DDP
|
55 |
+
1 - PMI/AN
|
56 |
+
|
57 |
+
Date
|
58 |
+
|
59 |
+
DDP/FE/PMI/AN/Amos Taylor, Jr. (X 5502):aib (25 November 1968)
|
60 |
+
|
61 |
+
201-289248
|
space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/space/jfk_text/104-10014-10051.md
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
2025 RELEASE UNDER THE PRESIDENT JOHN F. KENNEDY ASSASSINATION RECORDS ACT OF 1992
|
2 |
+
|
3 |
+
SECRET
|
4 |
+
IMS(FABOSS)
|
5 |
+
|
6 |
+
SECRET
|
7 |
+
FRP: ,2,
|
8 |
+
|
9 |
+
STAFF
|
10 |
+
|
11 |
+
ACTION: C/EUR/NOR (729) INFO: EUDORECORD, EUR/LGL, MDSX, ODPD RYBAT.(FILE,
|
12 |
+
|
13 |
+
OC/EURN, CIC/EUR (3/W)
|
14 |
+
|
15 |
+
96 3123036 ASO PAGE 001 IN 3123036
|
16 |
+
TOR: 081248Z FEB 96 (COPB 94608
|
17 |
+
SECRET 081247Z FEB 96 STAFF 19-6
|
18 |
+
CITE:(COPENHAGEN)94608
|
19 |
+
|
20 |
+
TO: IMMEDIATE DIRECTOR.
|
21 |
+
|
22 |
+
FOR: LIMIT EUR/(NOR) INFO DC/EURN) CIC (EU, EUR/LGL)
|
23 |
+
|
24 |
+
SLUGS: WNINTEL RYBAT
|
25 |
+
|
26 |
+
SUBJECT: RELEASE OF CLASSIFIED DOCUMENT
|
27 |
+
|
28 |
+
REF: DIRECTOR 633349 96 3117723
|
29 |
+
|
30 |
+
TEXT:
|
31 |
+
|
32 |
+
1. ACTION REQUIRED: SEE PARA 2.
|
33 |
+
|
34 |
+
2. THE FAX (STATION) RECEIVED APPEARS TO BE INCOMPLETE. IT
|
35 |
+
CONTAINED A COVER SHEET, A ONE-PAGE COPENHAGEN) CABLE STATING "NO
|
36 |
+
TRACES" AND THE FIRST PAGE OF A DIRECTOR CABLE REQUESTING TRACES ON
|
37 |
+
LEE HARVEY ((OSWALD)). UNLESS THE MISSING PORTIONS OF THE DIRECTOR
|
38 |
+
CABLE HAVE SOME BEARING ON (DENMARK, STATION) CANNOT MAKE A CASE
|
39 |
+
AGAINST RELEASE OF THIS MATERIAL WE WOULD INSIST, HOWEVER, THAT
|
40 |
+
CRYPTS BE DELETED - AS REF INDICATED WOULD BE THE CASE.
|
41 |
+
|
42 |
+
3. PLEASE KEEP US APPRISED OF DATE THESE DOCS WILL BE RELEASED
|
43 |
+
SO THAT (STATION) MAY INFORM AMBASSADOR AND OUR LIAISON SERVICE
|
44 |
+
CHIEFS.
|
45 |
+
|
46 |
+
4. CL BY: 0716497 CL REASON: 1.5(C) DECL ON: X1
|
47 |
+
|
48 |
+
4....FILE: 021-120-004/1. DECL DRV. HUM 4-82.
|
49 |
+
|
50 |
+
END OF MESSAGE SECRET
|
51 |
+
|
52 |
+
SECRET
|
53 |
+
|
54 |
+
DO NOT DESTROY
|
55 |
+
CROSS FILE COPY FOR:
|
56 |
+
201-0289248
|