prashantmatlani commited on
Commit
0ea40d5
·
1 Parent(s): 3120de3

initial commit

Browse files
Files changed (7) hide show
  1. .gitignore +18 -0
  2. app.py +60 -0
  3. core_logic.py +68 -0
  4. requirements.txt +7 -0
  5. storage.py +35 -0
  6. styles.css +11 -0
  7. tools.py +40 -0
.gitignore ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ venv/
2
+ node_modules/
3
+ *.log
4
+
5
+ # Python
6
+ __pycache__/
7
+ *.pyc
8
+
9
+ # Env
10
+ .env
11
+
12
+ # VS Code / Visual Studio
13
+ .vs/
14
+ .vscode/
15
+
16
+ # OS
17
+ .DS_Store
18
+ Thumbs.db
app.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 
2
+ # ./app.py
3
+
4
+ """
5
+ The Interface Skeleton - The code sets up the navigation panel and the multimodal chat interface
6
+ """
7
+
8
+ import gradio as gr
9
+ from core_logic import chat_function
10
+ from storage import save_chat, load_history
11
+
12
+ with gr.Blocks(css="styles.css", theme=gr.themes.Soft()) as demo:
13
+ # State variables for persistence
14
+ current_chat_id = gr.State("")
15
+ session_history = gr.State([])
16
+
17
+ with gr.Row():
18
+ # --- SIDEBAR (Navigation Panel) ---
19
+ with gr.Column(scale=1, variant="secondary"):
20
+ gr.Markdown("## 🛠️ Agent Architect")
21
+ new_btn = gr.Button("➕ New Chat", variant="primary")
22
+
23
+ gr.Markdown("### 🕒 Recent Conversations")
24
+ # This would be populated from storage.py
25
+ history_list = gr.Dataset(
26
+ components=[gr.Textbox(visible=False)],
27
+ label="",
28
+ samples=load_history()
29
+ )
30
+
31
+ gr.Markdown("---")
32
+ download_format = gr.Radio([".txt", ".pdf", ".docx"], label="Export Format")
33
+ export_btn = gr.Button("📥 Download Current Chat")
34
+
35
+ # --- MAIN CHAT INTERFACE ---
36
+ with gr.Column(scale=4):
37
+ chatbot = gr.Chatbot(
38
+ show_label=False,
39
+ elem_id="chat-window",
40
+ height=750,
41
+ type="messages",
42
+ multimodal=True
43
+ )
44
+
45
+ with gr.Row():
46
+ user_input = gr.MultimodalTextbox(
47
+ show_label=False,
48
+ placeholder="Describe your agentic architecture or upload code...",
49
+ file_types=[".py", ".pdf", ".js", ".md", ".txt", ".docx"],
50
+ file_count="multiple"
51
+ )
52
+
53
+ # --- EVENT HANDLERS ---
54
+ def handle_user_msg(message, history):
55
+ # This will link to our core_logic.py
56
+ return chat_function(message, history)
57
+
58
+ user_input.submit(handle_user_msg, [user_input, chatbot], [user_input, chatbot])
59
+
60
+ demo.launch()
core_logic.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # ./core_logic.py
3
+
4
+ """
5
+ The Inference Engine - Where the "Technical Genius" persona lives. It uses the huggingface_hub InferenceClient to run the model without local CPU strain
6
+ """
7
+
8
+ import os
9
+ from huggingface_hub import InferenceClient
10
+ from tools import web_search, parse_file
11
+
12
+ # Recommended: Qwen2.5-Coder-32B or Llama-3.1-70B-Instruct
13
+ #client = InferenceClient("Qwen/Qwen2.5-Coder-32B-Instruct", token=os.getenv("HF_TOKEN"))
14
+ client = InferenceClient("deepseek-ai/DeepSeek-V4-Pro", token=os.getenv("HF_TOKEN"))
15
+
16
+ SYSTEM_PROMPT = """
17
+ You are the 'Silicon Architect'�a master-stroke creative genius in AI Engineering and Technical Architecture.
18
+ Your goal is to provide production-grade, highly optimized solutions for web and mobile AI applications.
19
+
20
+ CORE DIRECTIVES:
21
+ 1. ARCHITECTURAL RIGOR: Always consider scalability, async patterns, and state management.
22
+ 2. AGENTIC EXPERTISE: You understand recurrent-depth simulations, tool-calling, and autonomous loops.
23
+ 3. CODE QUALITY: Write clean, PEP 8 compliant, and secure Python/JS code.
24
+ 4. INNOVATION: Suggest the latest libraries and frameworks (FastAPI, LangGraph, Pydantic AI).
25
+ 5. RESEARCH: If the user asks about new tech, use your Web Search capability to provide factual, up-to-date documentation.
26
+
27
+ When a user provides files, analyze the code structure and logic before proposing changes.
28
+ """
29
+
30
+ def chat_function(message, history):
31
+ # 1. Handle Multimodal Input (Files)
32
+ files_content = ""
33
+ user_text = message["text"]
34
+
35
+ if message["files"]:
36
+ for file_data in message["files"]:
37
+ # Gradio file objects have a .path attribute
38
+ files_content += parse_file(file_data)
39
+
40
+ # 2. Logic for "Web Search" trigger
41
+ # A simple keyword trigger or the LLM can decide. For now, we look for 'search' or 'docs'.
42
+ if "search" in user_text.lower() or "documentation" in user_text.lower():
43
+ search_query = user_text.replace("search", "").strip()
44
+ web_results = web_search(search_query)
45
+ full_user_input = f"RESEARCH RESULTS:\n{web_results}\n\nUSER FILES:\n{files_content}\n\nUSER QUESTION: {user_text}"
46
+ else:
47
+ full_user_input = f"USER FILES:\n{files_content}\n\nUSER QUESTION: {user_text}"
48
+
49
+ # 3. Construct Messages for Inference
50
+ messages = [{"role": "system", "content": SYSTEM_PROMPT}]
51
+ for turn in history:
52
+ messages.append({"role": "user", "content": turn[0]})
53
+ messages.append({"role": "assistant", "content": turn[1]})
54
+
55
+ messages.append({"role": "user", "content": full_user_input})
56
+
57
+ # 4. Stream Response
58
+ response = ""
59
+ for message_chunk in client.chat_completion(
60
+ messages,
61
+ max_tokens=2048,
62
+ stream=True,
63
+ temperature=0.2, # Low temperature for high technical precision
64
+ ):
65
+ token = message_chunk.choices[0].delta.content
66
+ if token:
67
+ response += token
68
+ yield response
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ gradio
2
+ huggingface_hub
3
+ python-dotenv
4
+ duckduckgo-search
5
+ pypdf
6
+ python-docx
7
+ pandas
storage.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # ./storage.py
3
+
4
+ """
5
+ Persistence Layer - Handles the "Save/Load" functionality using Hugging Face Dataset as a database
6
+ """
7
+
8
+ import json
9
+ import os
10
+ from huggingface_hub import HfApi, hf_hub_download
11
+
12
+ REPO_ID = "your-username/your-private-dataset" # Update this
13
+ api = HfApi(token=os.getenv("HF_TOKEN"))
14
+
15
+ def save_chat(chat_id, history):
16
+ """Save chat history as a JSON file to HF Dataset."""
17
+ file_path = f"{chat_id}.json"
18
+ with open(file_path, "w") as f:
19
+ json.dump(history, f)
20
+
21
+ api.upload_file(
22
+ path_or_fileobj=file_path,
23
+ path_in_repo=f"chats/{file_path}",
24
+ repo_id=REPO_ID,
25
+ repo_type="dataset"
26
+ )
27
+
28
+ def load_history():
29
+ """Retrieve all past chat IDs for the sidebar."""
30
+ try:
31
+ files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset")
32
+ chat_files = [f.split("/")[-1].replace(".json", "") for f in files if f.startswith("chats/")]
33
+ return [[f] for f in chat_files]
34
+ except Exception:
35
+ return []
styles.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ .sidebar {
4
+ background-color: #f8f9fa;
5
+ border-right: 1px solid #ddd;
6
+ height: 100vh;
7
+ }
8
+
9
+ .chatbot-container {
10
+ border-radius: 15px !important;
11
+ }
tools.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # ./tools.py
3
+
4
+ """
5
+ The Research & Extraction Engine - The module handles "Web Search" via Tavily and the parsing of uploaded files (PDFs, Python scripts, etc.)
6
+ """
7
+
8
+ import os
9
+ from tavily import TavilyClient
10
+ from pypdf import PdfReader
11
+ import docx
12
+
13
+ # Initialize Tavily
14
+ tavily = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
15
+
16
+ def web_search(query: str):
17
+ """Perform a technical search for documentation or latest AI trends."""
18
+ search_result = tavily.search(query=query, search_depth="advanced", max_results=5)
19
+ context = "\n".join([f"Source: {r['url']}\nContent: {r['content']}" for r in search_result['results']])
20
+ return context
21
+
22
+ def parse_file(file_path):
23
+ """Extract text from various file formats for the LLM to process."""
24
+ ext = os.path.splitext(file_path)[-1].lower()
25
+ text = f"--- File: {os.path.basename(file_path)} ---\n"
26
+
27
+ if ext == ".pdf":
28
+ reader = PdfReader(file_path)
29
+ for page in reader.pages:
30
+ text += page.extract_text()
31
+ elif ext == ".docx":
32
+ doc = docx.Document(file_path)
33
+ text += "\n".join([para.text for para in doc.paragraphs])
34
+ elif ext in [".py", ".txt", ".md", ".html", ".js", ".yaml", ".toml"]:
35
+ with open(file_path, "r", encoding="utf-8") as f:
36
+ text += f.read()
37
+ else:
38
+ text += "[Non-text file detected or unsupported format]"
39
+
40
+ return text + "\n---\n"