Chirag20 commited on
Commit
e55e243
·
1 Parent(s): 340140e

added minimal frontendd

Browse files
Files changed (4) hide show
  1. api.py +6 -1
  2. ingest.py +1 -0
  3. requirements.txt +1 -0
  4. static/index.html +143 -0
api.py CHANGED
@@ -1,5 +1,7 @@
1
  from fastapi import FastAPI, HTTPException
2
  from pydantic import BaseModel
 
 
3
 
4
  from ingest import ingest_repository
5
  from query import (
@@ -11,7 +13,10 @@ from query import (
11
 
12
 
13
  app = FastAPI(title="RAG Backend", version="1.0.0")
14
-
 
 
 
15
 
16
  class LoadRepoRequest(BaseModel):
17
  repo_url: str
 
1
  from fastapi import FastAPI, HTTPException
2
  from pydantic import BaseModel
3
+ from fastapi.staticfiles import StaticFiles
4
+ from fastapi.responses import FileResponse
5
 
6
  from ingest import ingest_repository
7
  from query import (
 
13
 
14
 
15
  app = FastAPI(title="RAG Backend", version="1.0.0")
16
+ app.mount("/static", StaticFiles(directory="static"), name="static")
17
+ @app.get("/")
18
+ def index():
19
+ return FileResponse("static/index.html")
20
 
21
  class LoadRepoRequest(BaseModel):
22
  repo_url: str
ingest.py CHANGED
@@ -7,6 +7,7 @@ from langchain_text_splitters import RecursiveCharacterTextSplitter
7
  from langchain_community.embeddings import HuggingFaceEmbeddings
8
 
9
 
 
10
  def get_repo_name(repo_url):
11
  cleaned = repo_url.rstrip("/")
12
  name = cleaned.split("/")[-1]
 
7
  from langchain_community.embeddings import HuggingFaceEmbeddings
8
 
9
 
10
+
11
  def get_repo_name(repo_url):
12
  cleaned = repo_url.rstrip("/")
13
  name = cleaned.split("/")[-1]
requirements.txt CHANGED
@@ -11,3 +11,4 @@ sentence-transformers
11
  gitpython
12
  python-dotenv
13
  pydantic
 
 
11
  gitpython
12
  python-dotenv
13
  pydantic
14
+ aiofiles
static/index.html ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>RepoQA</title>
6
+ <style>
7
+ * { box-sizing: border-box; margin: 0; padding: 0; }
8
+ body { font-family: sans-serif; background: #0d1117; color: #e6edf3; height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; }
9
+ .container { width: 100%; max-width: 720px; padding: 24px; display: flex; flex-direction: column; gap: 16px; }
10
+ h1 { font-size: 20px; font-weight: 600; color: #58a6ff; }
11
+ .repo-bar { display: flex; gap: 8px; }
12
+ input { flex: 1; padding: 10px 14px; border-radius: 8px; border: 1px solid #30363d; background: #161b22; color: #e6edf3; font-size: 14px; outline: none; }
13
+ input:focus { border-color: #58a6ff; }
14
+ button { padding: 10px 18px; border-radius: 8px; border: none; background: #238636; color: white; font-size: 14px; cursor: pointer; }
15
+ button:hover { background: #2ea043; }
16
+ button:disabled { background: #21262d; color: #484f58; cursor: not-allowed; }
17
+ .chat-box { background: #161b22; border: 1px solid #30363d; border-radius: 10px; height: 420px; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 12px; }
18
+ .msg { max-width: 85%; padding: 10px 14px; border-radius: 8px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; }
19
+ .msg.user { align-self: flex-end; background: #1f6feb; color: white; }
20
+ .msg.bot { align-self: flex-start; background: #21262d; color: #e6edf3; }
21
+ .msg.system { align-self: center; color: #8b949e; font-size: 13px; font-style: italic; }
22
+ .input-bar { display: flex; gap: 8px; }
23
+ #status { font-size: 13px; color: #8b949e; min-height: 18px; }
24
+ </style>
25
+ </head>
26
+ <body>
27
+ <div class="container">
28
+ <h1>RepoQA — Chat with any GitHub Repo</h1>
29
+
30
+ <div class="repo-bar">
31
+ <input id="repoUrl" placeholder="https://github.com/user/repo" />
32
+ <button id="loadBtn" onclick="loadRepo()">Load Repo</button>
33
+ </div>
34
+
35
+ <div id="status"></div>
36
+
37
+ <div class="chat-box" id="chatBox">
38
+ <div class="msg system">Load a repo to start chatting. Type /end to reset.</div>
39
+ </div>
40
+
41
+ <div class="input-bar">
42
+ <input id="questionInput" placeholder="Ask something about the repo..." onkeydown="if(event.key==='Enter') sendMessage()" disabled />
43
+ <button id="askBtn" onclick="sendMessage()" disabled>Send</button>
44
+ </div>
45
+ </div>
46
+
47
+ <script>
48
+ let repoName = null;
49
+
50
+ function setStatus(msg) {
51
+ document.getElementById("status").textContent = msg;
52
+ }
53
+
54
+ function addMessage(text, type) {
55
+ const box = document.getElementById("chatBox");
56
+ const div = document.createElement("div");
57
+ div.className = "msg " + type;
58
+ div.textContent = text;
59
+ box.appendChild(div);
60
+ box.scrollTop = box.scrollHeight;
61
+ }
62
+
63
+ async function loadRepo() {
64
+ const url = document.getElementById("repoUrl").value.trim();
65
+ if (!url) return;
66
+
67
+ const btn = document.getElementById("loadBtn");
68
+ btn.disabled = true;
69
+ setStatus("Loading repo... this may take a minute.");
70
+
71
+ try {
72
+ const res = await fetch("/load_repo", {
73
+ method: "POST",
74
+ headers: { "Content-Type": "application/json" },
75
+ body: JSON.stringify({ repo_url: url })
76
+ });
77
+ const data = await res.json();
78
+
79
+ if (res.ok) {
80
+ repoName = data.repo;
81
+ setStatus("Repo loaded: " + repoName);
82
+ addMessage("Repo loaded successfully. Ask me anything about it.", "system");
83
+ document.getElementById("questionInput").disabled = false;
84
+ document.getElementById("askBtn").disabled = false;
85
+ } else {
86
+ setStatus("Error: " + (data.detail || "Failed to load repo"));
87
+ }
88
+ } catch (e) {
89
+ setStatus("Error: " + e.message);
90
+ }
91
+
92
+ btn.disabled = false;
93
+ }
94
+
95
+ async function sendMessage() {
96
+ const input = document.getElementById("questionInput");
97
+ const question = input.value.trim();
98
+ if (!question || !repoName) return;
99
+
100
+ if (question === "/end") {
101
+ repoName = null;
102
+ input.value = "";
103
+ input.disabled = true;
104
+ document.getElementById("askBtn").disabled = true;
105
+ document.getElementById("repoUrl").value = "";
106
+ document.getElementById("chatBox").innerHTML = '<div class="msg system">Session ended. Load a new repo to start again.</div>';
107
+ setStatus("");
108
+ return;
109
+ }
110
+
111
+ addMessage(question, "user");
112
+ input.value = "";
113
+ input.disabled = true;
114
+ document.getElementById("askBtn").disabled = true;
115
+ setStatus("Thinking...");
116
+
117
+ try {
118
+ const res = await fetch("/ask", {
119
+ method: "POST",
120
+ headers: { "Content-Type": "application/json" },
121
+ body: JSON.stringify({ repo_name: repoName, question: question })
122
+ });
123
+ const data = await res.json();
124
+
125
+ if (res.ok) {
126
+ addMessage(data.answer, "bot");
127
+ setStatus("");
128
+ } else {
129
+ addMessage("Error: " + (data.detail || "Something went wrong"), "system");
130
+ setStatus("");
131
+ }
132
+ } catch (e) {
133
+ addMessage("Error: " + e.message, "system");
134
+ setStatus("");
135
+ }
136
+
137
+ input.disabled = false;
138
+ document.getElementById("askBtn").disabled = false;
139
+ input.focus();
140
+ }
141
+ </script>
142
+ </body>
143
+ </html>