davex-ai commited on
Commit
003266e
·
0 Parent(s):
Files changed (6) hide show
  1. README.md +205 -0
  2. ai.py +22 -0
  3. fake_ai.py +52 -0
  4. github_client.py +327 -0
  5. main.py +43 -0
  6. requirements.txt +26 -0
README.md ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🚀 ARCHON
2
+ <p align="center">
3
+ <img src="https://capsule-render.vercel.app/api?type=waving&color=0:6366f1,100:8b5cf6&height=200&section=header&text=Repo%20Interview%20Generator&fontSize=40&fontColor=ffffff" />
4
+ </p>
5
+
6
+ <p align="center">
7
+ <img src="https://img.shields.io/badge/Backend-FastAPI-009688?style=for-the-badge" />
8
+ <img src="https://img.shields.io/badge/Language-Python-3776AB?style=for-the-badge" />
9
+ <img src="https://img.shields.io/badge/AI-RAG%20Pipeline-8b5cf6?style=for-the-badge" />
10
+ <img src="https://img.shields.io/badge/Embeddings-SentenceTransformers-orange?style=for-the-badge" />
11
+ <img src="https://img.shields.io/badge/Status-Production%20Ready-success?style=for-the-badge" />
12
+ </p>
13
+
14
+ <p align="center">
15
+ <img src="https://readme-typing-svg.herokuapp.com?font=Fira+Code&size=20&pause=1000&color=8B5CF6&center=true&vCenter=true&width=600&lines=Analyze+Any+GitHub+Repo;Generate+Deep+Interview+Questions;Fallback+AI+Without+LLMs;Built+for+Real+Engineering+Insight" />
16
+ </p>
17
+
18
+ ---
19
+
20
+ ## 🧠 What is this?
21
+
22
+ A system that **analyzes any GitHub repository** and generates **deep technical interview questions + answers** based on:
23
+
24
+ * Architecture
25
+ * Scalability
26
+ * Tradeoffs
27
+ * Real-world engineering decisions
28
+
29
+ ⚡ Works even without LLM access using a **fallback heuristic engine**.
30
+
31
+ ---
32
+
33
+ ## ✨ Features
34
+
35
+ ### 🔍 Repository Analysis
36
+
37
+ * Fetches and parses GitHub repositories via API
38
+ * Prioritizes important files (core logic > boilerplate)
39
+ * Supports multiple languages
40
+
41
+ ### 🧩 Intelligent Chunking
42
+
43
+ * Breaks code into meaningful chunks
44
+ * Filters noise (non-informative code)
45
+ * Preserves structural context
46
+
47
+ ### 🧠 Embedding + Retrieval (RAG)
48
+
49
+ * Uses **SentenceTransformers**
50
+ * Retrieves most relevant code sections
51
+ * Builds contextual understanding of system design
52
+
53
+ ### 🤖 AI Question Generation
54
+
55
+ * Generates interview-level questions on:
56
+
57
+ * Architecture decisions
58
+ * Scalability concerns
59
+ * Tradeoffs
60
+
61
+ ### ⚡ Fallback Mode (No LLM Required)
62
+
63
+ * Automatically switches to **rule-based generation**
64
+ * Uses detected signals:
65
+
66
+ * API usage
67
+ * State management
68
+ * Auth systems
69
+ * Async logic
70
+
71
+ ---
72
+
73
+ ## 🧱 System Architecture
74
+
75
+ ```txt
76
+ GitHub Repo
77
+
78
+ File Fetching + Prioritization
79
+
80
+ Chunking + Filtering
81
+
82
+ Embeddings (SentenceTransformers)
83
+
84
+ Vector Similarity Retrieval
85
+
86
+ Context Builder
87
+
88
+ AI Question Generator
89
+
90
+ Fallback Engine (if LLM unavailable)
91
+ ```
92
+
93
+ ---
94
+
95
+ ## 🛠️ Tech Stack
96
+
97
+ ```bash
98
+ Backend:
99
+ - FastAPI
100
+ - Python
101
+
102
+ AI / ML:
103
+ - SentenceTransformers
104
+ - Cosine Similarity (Sklearn)
105
+
106
+ Data:
107
+ - GitHub REST API
108
+
109
+ Frontend:
110
+ - Minimal Web UI (React / HTML)
111
+
112
+ Optional:
113
+ - OpenAI API (LLM generation)
114
+ ```
115
+
116
+ ---
117
+
118
+ ## ⚙️ How it Works
119
+
120
+ 1. Input a GitHub repo URL
121
+ 2. System fetches and filters key files
122
+ 3. Code is chunked and embedded
123
+ 4. Relevant chunks are retrieved
124
+ 5. Questions are generated using:
125
+
126
+ * LLM (if available)
127
+ * OR fallback heuristic engine
128
+
129
+ ---
130
+
131
+ ## 📡 API Usage
132
+
133
+ ### POST `/analyze`
134
+
135
+ ```json
136
+ {
137
+ "repo_url": "https://github.com/user/repo",
138
+ "num_questions": 5
139
+ }
140
+ ```
141
+
142
+ ### Response
143
+
144
+ ```json
145
+ {
146
+ "repo": "...",
147
+ "mode": "mock",
148
+ "questions": [
149
+ {
150
+ "id": 1,
151
+ "question": "...",
152
+ "answer": "..."
153
+ }
154
+ ]
155
+ }
156
+ ```
157
+
158
+ ---
159
+
160
+ ## ⚠️ Challenges Solved
161
+
162
+ * Large repo handling (chunking + prioritization)
163
+ * Token limitations (retrieval instead of full context)
164
+ * LLM dependency → solved with fallback system
165
+ * Noise reduction in code analysis
166
+
167
+ ---
168
+
169
+ ## 💡 Future Improvements
170
+
171
+ * 🔥 Dynamic repo-type detection (ML, backend, real-time, etc.)
172
+ * 📊 Question difficulty levels (junior → senior)
173
+ * 🔗 Follow-up interview questions
174
+ * 🧠 Hybrid LLM + rule-based reasoning
175
+ * ⚡ Caching + performance optimization
176
+
177
+ ---
178
+
179
+ ## 🧑‍💻 Author
180
+
181
+ Built by **Dave** — aspiring systems engineer ⚡
182
+
183
+ ---
184
+
185
+ ## 🎬 Demo
186
+
187
+ <p align="center">
188
+ <img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExZ2Z4b2h3YzJ5dTFoMGN6dGx6eTVjYjZ0d2VtZ2w0N2JkNnR3b2p5ZyZlcD12MV9naWZzX3NlYXJjaCZjdD1n/26tn33aiTi1jkl6H6/giphy.gif" width="500" />
189
+ </p>
190
+
191
+ ---
192
+
193
+ ## ⭐ Support
194
+
195
+ If this project helped or inspired you:
196
+
197
+ * ⭐ Star the repo
198
+ * 🍴 Fork it
199
+ * 🧠 Build something even crazier
200
+
201
+ ---
202
+
203
+ <p align="center">
204
+ <b>“Don’t just read code. Interrogate it.”</b>
205
+ </p>
ai.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from openai import OpenAI
2
+ import os
3
+ from openai import OpenAI
4
+
5
+ client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
6
+
7
+ def call_llm(prompt):
8
+ response = client.chat.completions.create(
9
+ model="gpt-4o-mini",
10
+ messages=[
11
+ {"role": "system", "content": "You are a senior software engineer."},
12
+ {"role": "user", "content": prompt}
13
+ ],
14
+ temperature=0.7
15
+ )
16
+ return response.choices[0].message.content
17
+ clear
18
+
19
+ git pull space
20
+ git add .
21
+ git commit -m "files"
22
+ git push space master
fake_ai.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def generate_mock_questions(chunks, num_questions=5):
2
+ questions = []
3
+
4
+ context_text = " ".join([c["chunk"].lower() for c in chunks])
5
+
6
+ # Heuristic signals (lightweight, no LLM)
7
+ signals = {
8
+ "api": "fetch" in context_text or "axios" in context_text,
9
+ "auth": "auth" in context_text or "login" in context_text,
10
+ "database": "db" in context_text or "firebase" in context_text,
11
+ "state": "useState" in context_text or "state" in context_text,
12
+ "async": "async" in context_text or "await" in context_text,
13
+ }
14
+
15
+ if signals["api"]:
16
+ questions.append({
17
+ "question": "How would you design this API layer for scalability and fault tolerance?",
18
+ "answer": "Introduce caching, retries, rate limiting, and abstraction layers to decouple API logic."
19
+ })
20
+
21
+ if signals["database"]:
22
+ questions.append({
23
+ "question": "What are the tradeoffs of using a NoSQL database like Firebase in this system?",
24
+ "answer": "It offers flexibility and scalability but may lack strong consistency and complex querying."
25
+ })
26
+
27
+ if signals["state"]:
28
+ questions.append({
29
+ "question": "How would you manage global state in a growing frontend application?",
30
+ "answer": "Use centralized state management (Context, Redux) and avoid excessive prop drilling."
31
+ })
32
+
33
+ if signals["auth"]:
34
+ questions.append({
35
+ "question": "What security concerns exist in this authentication flow?",
36
+ "answer": "Token leakage, improper session handling, and lack of validation are key risks."
37
+ })
38
+
39
+ if signals["async"]:
40
+ questions.append({
41
+ "question": "How would you handle concurrency and async operations safely in this system?",
42
+ "answer": "Use proper error handling, cancellation, and avoid race conditions with controlled state updates."
43
+ })
44
+
45
+ # fallback generic
46
+ while len(questions) < num_questions:
47
+ questions.append({
48
+ "question": "What architectural improvements would you suggest for this system?",
49
+ "answer": "Improve modularity, scalability, and separation of concerns across components."
50
+ })
51
+
52
+ return questions[:num_questions]
github_client.py ADDED
@@ -0,0 +1,327 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+ from sentence_transformers import SentenceTransformer
3
+ from sklearn.metrics.pairwise import cosine_similarity
4
+ import requests
5
+ import os
6
+ from dotenv import load_dotenv
7
+
8
+ from ai import call_llm
9
+ from fake_ai import generate_mock_questions
10
+
11
+ load_dotenv()
12
+
13
+ GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
14
+
15
+ HEADERS = {
16
+ "Accept": "application/vnd.github+json"
17
+ }
18
+
19
+ if GITHUB_TOKEN:
20
+ HEADERS["Authorization"] = f"Bearer {GITHUB_TOKEN}"
21
+
22
+
23
+
24
+ def get_repo_tree(owner, repo, branch):
25
+ url = f"https://api.github.com/repos/{owner}/{repo}/git/trees/{branch}?recursive=1"
26
+
27
+ res = requests.get(url, headers=HEADERS)
28
+
29
+ if res.status_code != 200:
30
+ raise Exception(f"GitHub API error: {res.json()}")
31
+
32
+ return res.json()["tree"]
33
+
34
+
35
+ ALLOWED_EXTENSIONS = (
36
+ ".py", ".js", ".ts", ".jsx", ".tsx", ".md", ".json",
37
+ ".html", ".htm", ".css", ".scss", ".sass", ".less",
38
+ ".csv", ".sql", ".xml", ".sh", ".bash", ".bat", ".ps1", ".ipynb",
39
+ ".php", ".rb", ".java", ".go", ".cs", ".scala", ".kt", ".kts", ".ex", ".exs",
40
+ ".swift", ".m", ".mm", ".dart", ".rst", ".gitattributes"
41
+ )
42
+
43
+ IMPORTANT_FILES = [
44
+ "server/",
45
+ "src/",
46
+ "app/",
47
+ "index",
48
+ "main",
49
+ "api",
50
+ ]
51
+
52
+ def filter_files(tree):
53
+ return [
54
+ file for file in tree
55
+ if file["type"] == "blob" and file["path"].endswith(ALLOWED_EXTENSIONS)
56
+ ]
57
+
58
+
59
+ def get_file_content(owner, repo, path):
60
+ url = f"https://api.github.com/repos/{owner}/{repo}/contents/{path}"
61
+
62
+ res = requests.get(url, headers=HEADERS)
63
+
64
+ if res.status_code != 200:
65
+ return None
66
+
67
+ data = res.json()
68
+
69
+ content = base64.b64decode(data["content"]).decode("utf-8", errors="ignore")
70
+
71
+ return content
72
+
73
+
74
+ from urllib.parse import urlparse
75
+
76
+
77
+ def parse_github_url(url: str):
78
+ path = urlparse(url).path.strip("/")
79
+ parts = path.split("/")
80
+
81
+ if len(parts) < 2:
82
+ raise ValueError("Invalid GitHub URL")
83
+
84
+ owner, repo = parts[0], parts[1]
85
+ return owner, repo
86
+
87
+ def get_default_branch(owner, repo):
88
+ url = f"https://api.github.com/repos/{owner}/{repo}"
89
+ res = requests.get(url, headers=HEADERS)
90
+ if res.status_code != 200:
91
+ raise Exception(f"GitHub API error: {res.json()}")
92
+ return res.json()["default_branch"]
93
+
94
+ def fetch_repo_contents(repo_url):
95
+
96
+ owner, repo = parse_github_url(repo_url)
97
+ branch = get_default_branch(owner, repo)
98
+
99
+ tree = get_repo_tree(owner, repo, branch)
100
+ files = filter_files(tree)
101
+
102
+ results = []
103
+
104
+ for file in prioritize_files(files)[:20]:
105
+ content = get_file_content(owner, repo, file["path"])
106
+
107
+ if content:
108
+ results.append({
109
+ "path": file["path"],
110
+ "content": content
111
+ })
112
+
113
+
114
+ return results
115
+ def score_file(path):
116
+ score = 0
117
+
118
+ if "README" in path:
119
+ score += 3
120
+ if any(key in path.lower() for key in IMPORTANT_FILES):
121
+ score += 5
122
+ if path.endswith((".js", ".ts", ".py", ".java", ".jsx", ".c")):
123
+ score += 4
124
+
125
+ return score
126
+
127
+
128
+ def prioritize_files(files):
129
+ return sorted(files, key=lambda f: score_file(f["path"]), reverse=True)
130
+
131
+ def chunk_text(text, size=1000):
132
+ lines = text.split("\n")
133
+ chunks = []
134
+ current = []
135
+
136
+ current_len = 0
137
+
138
+ for line in lines:
139
+ current.append(line)
140
+ current_len += len(line)
141
+
142
+ if current_len >= size:
143
+ chunks.append("\n".join(current))
144
+ current = []
145
+ current_len = 0
146
+
147
+ if current:
148
+ chunks.append("\n".join(current))
149
+ return chunks
150
+
151
+ def process_files(files):
152
+ processed = []
153
+
154
+ for file in files:
155
+ chunks = chunk_text(file["content"], size=1000)
156
+
157
+ processed.append({
158
+ "path": file["path"],
159
+ "chunks": chunks
160
+ })
161
+
162
+ return processed
163
+
164
+ def classify_file(path):
165
+ if "server" in path or path.endswith(".py") or path.endswith(".js"):
166
+ return "backend"
167
+ if "client" in path or path.endswith(".jsx"):
168
+ return "frontend"
169
+ if "config" in path or path.endswith(".json"):
170
+ return "config"
171
+ return "other"
172
+
173
+ def filter_chunks(chunks):
174
+ return [
175
+ c for c in chunks
176
+ if len(c.strip()) > 50 and (
177
+ "import" in c or "function" in c or "class" in c
178
+ )
179
+ ]
180
+ def build_retrieval_query():
181
+ return """
182
+ core architecture system design scalability performance
183
+ state management data flow backend logic frontend interaction
184
+ real-time communication concurrency bottlenecks tradeoffs
185
+ """
186
+
187
+ def build_question_prompt(repo_summary, signals, num_questions):
188
+ return f"""
189
+ You are a senior software engineer conducting a deep technical interview.
190
+
191
+ Repository Summary:
192
+ {repo_summary}
193
+
194
+ Detected System Signals:
195
+ {signals}
196
+
197
+ Generate {num_questions} deep interview questions and strong answers.
198
+
199
+ Focus on:
200
+ - architecture decisions
201
+ - scalability challenges
202
+ - tradeoffs (e.g. WebSockets vs polling)
203
+ - real-world engineering issues
204
+
205
+ Avoid generic questions.
206
+ Format:
207
+ Q1:
208
+ A1:
209
+ """
210
+ embeddings = [
211
+ {
212
+ "chunk": "...",
213
+ "vector": [...]
214
+ }
215
+ ]
216
+
217
+ def retrieve(query_vector, embeddings, top_k=5):
218
+ scored = []
219
+
220
+ for item in embeddings:
221
+ score = cosine_similarity(
222
+ [query_vector],
223
+ [item["vector"]]
224
+ )[0][0]
225
+
226
+ scored.append((score, item))
227
+
228
+ scored = sorted(scored, key=lambda x: x[0], reverse=True)
229
+
230
+ return [item for _, item in scored[:top_k]]
231
+
232
+ def build_embeddings(processed_files):
233
+ index = []
234
+
235
+ for file in processed_files:
236
+ filtered = filter_chunks(file["chunks"])
237
+
238
+ for chunk in filtered:
239
+ vector = embed_text(chunk)
240
+
241
+ index.append({
242
+ "chunk": chunk,
243
+ "vector": vector,
244
+ "path": file["path"]
245
+ })
246
+
247
+ return index
248
+
249
+ def format_context(chunks):
250
+ return "\n\n".join([
251
+ f"[FILE: {c['path']}]\n{c['chunk'][:800]}"
252
+ for c in chunks
253
+ ])
254
+
255
+
256
+ def generate_questions_from_repo(repo_url, num_questions=5):
257
+ # 1. Fetch
258
+ files = fetch_repo_contents(repo_url)
259
+
260
+ # 2. Process
261
+ processed = process_files(files)
262
+
263
+ # 3. Build embeddings
264
+ embedding_index = build_embeddings(processed)
265
+
266
+ # 4. Build query
267
+ query = build_retrieval_query()
268
+ query_vector = embed_text(query)
269
+
270
+ # 5. Retrieve relevant chunks
271
+ top_chunks = retrieve(query_vector, embedding_index, top_k=8)
272
+
273
+ # 6. Build context
274
+ context = format_context(top_chunks)
275
+
276
+ # 7. Build final prompt
277
+ prompt = f"""
278
+ You are a senior software engineer conducting a deep technical interview.
279
+
280
+ Analyze this code context:
281
+
282
+ {context}
283
+
284
+ Generate {num_questions} deep technical interview questions and answers.
285
+
286
+ Focus on:
287
+ - architecture
288
+ - scalability
289
+ - tradeoffs
290
+ - real-world engineering challenges
291
+
292
+ Format:
293
+ Q1:
294
+ A1:
295
+ """
296
+ try:
297
+ result = call_llm(prompt)
298
+
299
+ return {
300
+ "mode": "llm",
301
+ "data": result
302
+ }
303
+
304
+ except Exception as e:
305
+ print("LLM failed, falling back to mock:", str(e))
306
+
307
+ mock = generate_mock_questions(top_chunks, num_questions)
308
+
309
+ return {
310
+ "mode": "mock",
311
+ "data": mock
312
+ }
313
+
314
+ model = SentenceTransformer("all-MiniLM-L6-v2")
315
+
316
+ def embed_text(text):
317
+ return model.encode(text)
318
+
319
+ repo_cache = {}
320
+
321
+ def get_or_create_embeddings(repo_url, processed):
322
+ if repo_url in repo_cache:
323
+ return repo_cache[repo_url]
324
+
325
+ embeddings = build_embeddings(processed)
326
+ repo_cache[repo_url] = embeddings
327
+ return embeddings
main.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from fastapi import FastAPI, HTTPException
3
+ from pydantic import BaseModel
4
+ from fastapi.middleware.cors import CORSMiddleware
5
+
6
+ from github_client import generate_questions_from_repo
7
+
8
+ app = FastAPI()
9
+ app.add_middleware(
10
+ CORSMiddleware,
11
+ allow_origins=["http://localhost:3000"], # Your Next.js frontend URL
12
+ allow_credentials=True,
13
+ allow_methods=["*"], # Allows POST, GET, etc.
14
+ allow_headers=["*"], # Allows Content-Type, Authorization, etc.
15
+ )
16
+
17
+ class RepoRequest(BaseModel):
18
+ repo_url: str
19
+ num_questions: int = 5
20
+
21
+
22
+ @app.get("/")
23
+ def home():
24
+ return {"message": "Repo Interview Generator API"}
25
+
26
+
27
+ @app.post("/analyze")
28
+ def analyze_repo(data: RepoRequest):
29
+ try:
30
+ result = generate_questions_from_repo(
31
+ data.repo_url,
32
+ data.num_questions
33
+ )
34
+
35
+ return {
36
+ "repo": data.repo_url,
37
+ "questions_requested": data.num_questions,
38
+ "mode": result["mode"],
39
+ "result": result["data"]
40
+ }
41
+
42
+ except Exception as e:
43
+ raise (HTTPException(status_code=500, detail=str(e)))
requirements.txt ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ fastapi==0.110.0
2
+ uvicorn[standard]==0.29.0
3
+
4
+ pydantic==2.6.4
5
+ python-dotenv==1.0.1
6
+
7
+ requests==2.31.0
8
+ httpx==0.27.0
9
+
10
+ openai==1.14.3
11
+
12
+ tiktoken==0.6.0
13
+
14
+ beautifulsoup4==4.12.3
15
+
16
+ gitpython==3.1.43
17
+
18
+ numpy==1.26.4
19
+ scikit-learn==1.4.2
20
+
21
+ tenacity==8.2.3
22
+ sentence-transformers==3.0.1
23
+
24
+
25
+ git remote add space https://huggingface.co/spaces/davex-ai/archon-backend
26
+ git push space master