Update app.py
Browse files
app.py
CHANGED
@@ -10,6 +10,8 @@ import torch.nn as nn
|
|
10 |
import torch.optim as optim
|
11 |
from torch.utils.data import DataLoader, TensorDataset
|
12 |
import base64
|
|
|
|
|
13 |
|
14 |
# Page Configuration
|
15 |
st.set_page_config(
|
@@ -79,6 +81,10 @@ def sanitize_label(label):
|
|
79 |
"""Remove invalid characters for Mermaid labels."""
|
80 |
return re.sub(r'[^\w\s-]', '', label).replace(' ', '_')
|
81 |
|
|
|
|
|
|
|
|
|
82 |
def parse_outline_to_mermaid(outline_text, search_agent):
|
83 |
"""Convert tree outline to Mermaid syntax with clickable nodes."""
|
84 |
lines = outline_text.strip().split('\n')
|
@@ -137,6 +143,45 @@ def get_download_link(file_path, mime_type="text/plain"):
|
|
137 |
b64 = base64.b64encode(data).decode()
|
138 |
return f'<a href="data:{mime_type};base64,{b64}" download="{file_path}">Download {file_path}</a>'
|
139 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
# Search Agents (Highest resolution social network default: X)
|
141 |
search_urls = {
|
142 |
"📚📖ArXiv": lambda k: f"/?q={quote(k)}",
|
@@ -150,10 +195,22 @@ search_urls = {
|
|
150 |
# Main App
|
151 |
st.title("🌳 AI Knowledge Tree Builder 🌱")
|
152 |
|
|
|
|
|
|
|
|
|
|
|
153 |
# Select Project Type
|
154 |
project_type = st.selectbox("Select Project Type", ["Code Project", "Papers Project", "AI Project"])
|
|
|
|
|
155 |
if 'current_tree' not in st.session_state:
|
156 |
-
|
|
|
|
|
|
|
|
|
|
|
157 |
|
158 |
# Select Search Agent for Node Links
|
159 |
search_agent = st.selectbox("Select Search Agent for Node Links", list(search_urls.keys()), index=5) # Default to X
|
@@ -163,9 +220,14 @@ new_node = st.text_input("Add New Node")
|
|
163 |
parent_node = st.text_input("Parent Node")
|
164 |
if st.button("Grow Tree 🌱") and new_node and parent_node:
|
165 |
st.session_state['current_tree'] = grow_tree(st.session_state['current_tree'], new_node, parent_node)
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
with open("current_tree.md", "w") as f:
|
167 |
f.write(st.session_state['current_tree'])
|
168 |
-
st.success(f"Added '{new_node}' under '{parent_node}'!")
|
169 |
|
170 |
# Display Mermaid Diagram
|
171 |
st.markdown("### Knowledge Tree Visualization")
|
|
|
10 |
import torch.optim as optim
|
11 |
from torch.utils.data import DataLoader, TensorDataset
|
12 |
import base64
|
13 |
+
import glob
|
14 |
+
import time
|
15 |
|
16 |
# Page Configuration
|
17 |
st.set_page_config(
|
|
|
81 |
"""Remove invalid characters for Mermaid labels."""
|
82 |
return re.sub(r'[^\w\s-]', '', label).replace(' ', '_')
|
83 |
|
84 |
+
def sanitize_filename(label):
|
85 |
+
"""Make a valid filename from a label."""
|
86 |
+
return re.sub(r'[^\w\s-]', '', label).replace(' ', '_')
|
87 |
+
|
88 |
def parse_outline_to_mermaid(outline_text, search_agent):
|
89 |
"""Convert tree outline to Mermaid syntax with clickable nodes."""
|
90 |
lines = outline_text.strip().split('\n')
|
|
|
143 |
b64 = base64.b64encode(data).decode()
|
144 |
return f'<a href="data:{mime_type};base64,{b64}" download="{file_path}">Download {file_path}</a>'
|
145 |
|
146 |
+
def save_tree_to_file(tree_text, parent_node, new_node):
|
147 |
+
"""Save tree to a markdown file with name based on nodes."""
|
148 |
+
root_node = tree_text.strip().split('\n')[0].split('.')[1].strip() if tree_text.strip() else "Knowledge_Tree"
|
149 |
+
filename = f"{sanitize_filename(root_node)}_{sanitize_filename(parent_node)}_{sanitize_filename(new_node)}_{int(time.time())}.md"
|
150 |
+
|
151 |
+
mermaid_code = parse_outline_to_mermaid(tree_text, "🔮Google") # Default search engine for saved trees
|
152 |
+
export_md = f"# Knowledge Tree: {root_node}\n\n## Outline\n{tree_text}\n\n## Mermaid Diagram\n```mermaid\n{mermaid_code}\n```"
|
153 |
+
|
154 |
+
with open(filename, "w") as f:
|
155 |
+
f.write(export_md)
|
156 |
+
return filename
|
157 |
+
|
158 |
+
def load_trees_from_files():
|
159 |
+
"""Load all saved tree markdown files."""
|
160 |
+
tree_files = glob.glob("*.md")
|
161 |
+
trees_dict = {}
|
162 |
+
|
163 |
+
for file in tree_files:
|
164 |
+
if file != "README.md" and file != "knowledge_tree.md": # Skip project README and temp export
|
165 |
+
try:
|
166 |
+
with open(file, 'r') as f:
|
167 |
+
content = f.read()
|
168 |
+
# Extract the tree name from the first line
|
169 |
+
match = re.search(r'# Knowledge Tree: (.*)', content)
|
170 |
+
if match:
|
171 |
+
tree_name = match.group(1)
|
172 |
+
else:
|
173 |
+
tree_name = os.path.splitext(file)[0]
|
174 |
+
|
175 |
+
# Extract the outline section
|
176 |
+
outline_match = re.search(r'## Outline\n(.*?)(?=\n## |$)', content, re.DOTALL)
|
177 |
+
if outline_match:
|
178 |
+
tree_outline = outline_match.group(1).strip()
|
179 |
+
trees_dict[f"{tree_name} ({file})"] = tree_outline
|
180 |
+
except Exception as e:
|
181 |
+
print(f"Error loading {file}: {e}")
|
182 |
+
|
183 |
+
return trees_dict
|
184 |
+
|
185 |
# Search Agents (Highest resolution social network default: X)
|
186 |
search_urls = {
|
187 |
"📚📖ArXiv": lambda k: f"/?q={quote(k)}",
|
|
|
195 |
# Main App
|
196 |
st.title("🌳 AI Knowledge Tree Builder 🌱")
|
197 |
|
198 |
+
# Sidebar with saved trees
|
199 |
+
st.sidebar.title("Saved Trees")
|
200 |
+
saved_trees = load_trees_from_files()
|
201 |
+
selected_saved_tree = st.sidebar.selectbox("Select a saved tree", ["None"] + list(saved_trees.keys()))
|
202 |
+
|
203 |
# Select Project Type
|
204 |
project_type = st.selectbox("Select Project Type", ["Code Project", "Papers Project", "AI Project"])
|
205 |
+
|
206 |
+
# Initialize or load tree
|
207 |
if 'current_tree' not in st.session_state:
|
208 |
+
if selected_saved_tree != "None" and selected_saved_tree in saved_trees:
|
209 |
+
st.session_state['current_tree'] = saved_trees[selected_saved_tree]
|
210 |
+
else:
|
211 |
+
st.session_state['current_tree'] = trees.get("ML Engineering", project_seeds[project_type])
|
212 |
+
elif selected_saved_tree != "None" and selected_saved_tree in saved_trees:
|
213 |
+
st.session_state['current_tree'] = saved_trees[selected_saved_tree]
|
214 |
|
215 |
# Select Search Agent for Node Links
|
216 |
search_agent = st.selectbox("Select Search Agent for Node Links", list(search_urls.keys()), index=5) # Default to X
|
|
|
220 |
parent_node = st.text_input("Parent Node")
|
221 |
if st.button("Grow Tree 🌱") and new_node and parent_node:
|
222 |
st.session_state['current_tree'] = grow_tree(st.session_state['current_tree'], new_node, parent_node)
|
223 |
+
|
224 |
+
# Save to a new file with the node names
|
225 |
+
saved_file = save_tree_to_file(st.session_state['current_tree'], parent_node, new_node)
|
226 |
+
st.success(f"Added '{new_node}' under '{parent_node}' and saved to {saved_file}!")
|
227 |
+
|
228 |
+
# Also update the temporary current_tree.md for compatibility
|
229 |
with open("current_tree.md", "w") as f:
|
230 |
f.write(st.session_state['current_tree'])
|
|
|
231 |
|
232 |
# Display Mermaid Diagram
|
233 |
st.markdown("### Knowledge Tree Visualization")
|