#!/usr/bin/env python3 import os import re import glob import streamlit as st import streamlit.components.v1 as components from transformers import pipeline from urllib.parse import quote from datetime import datetime import pytz # Page Configuration st.set_page_config( page_title="AI Knowledge Tree Builder ๐๐ฟ", page_icon="๐ณโจ", layout="wide", initial_sidebar_state="auto", ) # Predefined Knowledge Trees trees = { "Biology": """ 0. Biology Core Rules and Future Exceptions 1. Central Dogma DNA RNA Protein - Current CRISPR RNA editing ๐งช - Research Gene therapy siRNA ๐ฌ - Future Programmable genetics ๐ 2. Cell Origin - Current iPSCs organoids ๐ฆ - Research Synthetic cells ๐ฌ - Future De novo cell creation ๐ """, "AI Topics": """ 1. Major AI Industry Players ๐ 1. Research Leaders ๐ฏ - OpenAI: GPT-4 DALL-E Foundation Models ๐ต - Google: PaLM Gemini LLMs ๐ฆ - Anthropic: Claude Constitutional AI โก """, "Multiplayer Games": """ 0. Fantasy Domain Introduction 1. Setting the Scene - Current Create a high-fantasy realm ๐๏ธ - Research Add domain-specific entities ๐งโโ๏ธ - Future AI-generated worldbuilding ๐ """ } # Utility Functions def sanitize_filename(text): """Sanitize text for use in filenames.""" safe_text = re.sub(r'[^\w\s-]', ' ', text) safe_text = re.sub(r'\s+', ' ', safe_text) return safe_text.strip()[:50] def generate_timestamp_filename(query): """Generate a timestamped filename for saving files.""" central = pytz.timezone('US/Central') current_time = datetime.now(central) time_str = current_time.strftime("%I%M%p") date_str = current_time.strftime("%m%d%Y") safe_query = sanitize_filename(query) return f"{time_str} {date_str} ({safe_query}).md" def parse_outline_to_mermaid(outline_text): """Convert a tree outline to Mermaid syntax with clickable nodes.""" lines = outline_text.strip().split('\n') nodes = [] edges = [] clicks = [] stack = [] for line in lines: indent = len(line) - len(line.lstrip()) level = indent // 4 # 4 spaces per level text = line.strip() label = re.sub(r'^[#*\->\d\.\s]+', '', text).strip() if label: node_id = f"N{len(nodes)}" nodes.append(f'{node_id}["{label}"]') clicks.append(f'click {node_id} "?q={quote(label)}" _blank') if stack: parent_level = stack[-1][0] if level > parent_level: parent_id = stack[-1][1] edges.append(f"{parent_id} --> {node_id}") stack.append((level, node_id)) else: while stack and stack[-1][0] >= level: stack.pop() if stack: parent_id = stack[-1][1] edges.append(f"{parent_id} --> {node_id}") stack.append((level, node_id)) else: stack.append((level, node_id)) return "graph TD\n" + "\n".join(nodes + edges + clicks) def generate_mermaid_html(mermaid_code: str) -> str: """Generate HTML to center and display a Mermaid diagram.""" return f""" <html> <head> <script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script> <style> .centered-mermaid {{ display: flex; justify-content: center; margin: 20px auto; }} .mermaid {{ max-width: 800px; }} </style> </head> <body> <div class="mermaid centered-mermaid"> {mermaid_code} </div> <script> mermaid.initialize({{ startOnLoad: true }}); </script> </body> </html> """ def grow_tree(base_tree, new_node_name, parent_node): """Add a new node to the tree under a specified parent.""" lines = base_tree.strip().split('\n') new_lines = [] added = False for line in lines: new_lines.append(line) if parent_node in line and not added: indent = len(line) - len(line.lstrip()) new_lines.append(f"{' ' * (indent + 4)}- {new_node_name} ๐ฑ") added = True return "\n".join(new_lines) # AI Lookup @st.cache_resource def load_generator(): """Load a text generation model for AI lookups.""" return pipeline("text-generation", model="distilgpt2") # File Management def FileSidebar(): """Render a sidebar for managing Markdown files.""" st.sidebar.title("๐ Saved Interactions") md_files = glob.glob("*.md") for file in md_files: col1, col2, col3 = st.sidebar.columns([1, 3, 1]) with col1: if st.button("๐", key=f"open_{file}"): with open(file, 'r') as f: st.session_state['file_content'] = f.read() st.session_state['selected_file'] = file with col2: st.write(file) with col3: if st.button("๐", key=f"delete_{file}"): os.remove(file) st.rerun() if st.sidebar.button("Create New Note"): filename = generate_timestamp_filename("New Note") with open(filename, 'w') as f: f.write("# New Note\n") st.sidebar.success(f"Created {filename}") # Main App Logic st.title("๐ณ AI Knowledge Tree Builder ๐ฑ") st.markdown("Grow, visualize, and explore knowledge trees with AI!") # Handle Query Parameters query_params = st.query_params if 'q' in query_params: query = query_params['q'] st.subheader(f"AI Lookup for: {query}") generator = load_generator() response = generator(query, max_length=50)[0]['generated_text'] st.write(f"**Response:** {response}") filename = generate_timestamp_filename(query) with open(filename, 'w') as f: f.write(f"# Query: {query}\n\n## AI Response\n{response}") st.success(f"Saved to {filename}") else: # Tree Selection and Interaction if 'current_tree' not in st.session_state: st.session_state['current_tree'] = trees["Biology"] if 'selected_tree_name' not in st.session_state: st.session_state['selected_tree_name'] = "Biology" selected_tree = st.selectbox("Select Knowledge Tree", list(trees.keys()), key="tree_select") if selected_tree != st.session_state['selected_tree_name']: st.session_state['current_tree'] = trees[selected_tree] st.session_state['selected_tree_name'] = selected_tree # Tree Growth new_node = st.text_input("Add New Node (e.g., 'ML Pipeline')") parent_node = st.text_input("Parent Node to Attach To (e.g., 'Central Dogma')") if st.button("Grow Tree ๐ฑ") and new_node and parent_node: st.session_state['current_tree'] = grow_tree(st.session_state['current_tree'], new_node, parent_node) st.success(f"Added '{new_node}' under '{parent_node}'!") # Display Mermaid Diagram st.markdown("### Knowledge Tree Visualization") mermaid_code = parse_outline_to_mermaid(st.session_state['current_tree']) mermaid_html = generate_mermaid_html(mermaid_code) components.html(mermaid_html, height=600) # AI Lookup query = st.text_input("Enter Query for AI Lookup") if st.button("Perform AI Lookup ๐ค") and query: generator = load_generator() response = generator(query, max_length=50)[0]['generated_text'] st.write(f"**AI Response:** {response}") filename = generate_timestamp_filename(query) with open(filename, 'w') as f: f.write(f"# Query: {query}\n\n## AI Response\n{response}") st.success(f"Saved to {filename}") # File Viewer if 'file_content' in st.session_state: st.markdown("### Selected File") st.markdown(st.session_state['file_content']) # Sidebar FileSidebar() if __name__ == "__main__": st.sidebar.markdown("Explore and grow your knowledge trees!")