-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrecord_demo_final.py
More file actions
245 lines (201 loc) · 8.66 KB
/
record_demo_final.py
File metadata and controls
245 lines (201 loc) · 8.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#!/usr/bin/env python3
"""
FINAL DEMO - Document Upload + Real AI Chat with OpenAI
"""
import asyncio
import os
import shutil
from pathlib import Path
from playwright.async_api import async_playwright
OUTPUT_DIR = Path("docs/images")
GIF_PATH = OUTPUT_DIR / "demo.gif"
FRONTEND_URL = "http://localhost:3002"
SAMPLE_DOC = Path("sample_docs/product_guide.txt").absolute()
async def main():
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
frames_dir = OUTPUT_DIR / "frames"
if frames_dir.exists():
shutil.rmtree(frames_dir)
frames_dir.mkdir()
print("=" * 70)
print("FINAL DEMO: Document + Real AI Chat")
print("=" * 70)
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False, slow_mo=30)
ctx = await browser.new_context(viewport={"width": 1280, "height": 720})
page = await ctx.new_page()
fc = [0]
async def snap(d="", n=1):
for i in range(n):
fc[0] += 1
await page.screenshot(path=str(frames_dir / f"f_{fc[0]:03d}.png"))
if i == 0 and d: print(f" [{fc[0]:2d}] {d}")
await asyncio.sleep(0.08)
# 1. LANDING
print("\n[1] Landing")
await page.goto(FRONTEND_URL, timeout=30000)
await asyncio.sleep(1.5)
await snap("Info Naut", 3)
# 2. DASHBOARD
print("[2] Dashboard")
await page.goto(f"{FRONTEND_URL}/dashboard", timeout=30000)
await asyncio.sleep(1.5)
await snap("Dashboard", 3)
# 3. CREATE KB
print("[3] Create Knowledge Base")
await page.goto(f"{FRONTEND_URL}/dashboard/knowledge/new", timeout=30000)
await asyncio.sleep(1)
await snap("New KB", 2)
await page.fill('input', 'AI Product Docs')
await asyncio.sleep(0.3)
await snap("Name filled", 2)
textarea = page.locator('textarea').first
if await textarea.count() > 0:
await textarea.fill('Documentation for AI assistant')
await asyncio.sleep(0.3)
await snap("Description", 2)
await page.click('button:has-text("Create")')
await asyncio.sleep(2)
await snap("KB Created!", 3)
# 4. GO TO KB AND UPLOAD DOC
print("[4] Upload Document")
await page.goto(f"{FRONTEND_URL}/dashboard/knowledge", timeout=30000)
await asyncio.sleep(1.5)
await snap("KB List", 2)
# Click first KB
kb_cards = page.locator('a[href*="/knowledge/"]')
if await kb_cards.count() > 0:
await kb_cards.first.click()
await asyncio.sleep(2)
await snap("Inside KB", 2)
# Upload file
file_input = page.locator('input[type="file"]')
if await file_input.count() > 0:
await file_input.set_input_files(str(SAMPLE_DOC))
print(" Uploading document...")
await asyncio.sleep(3)
await snap("Document Uploaded!", 3)
else:
# Try upload button
upload_btn = page.locator('button:has-text("Upload")')
if await upload_btn.count() > 0:
await upload_btn.first.click()
await asyncio.sleep(1)
file_input = page.locator('input[type="file"]')
if await file_input.count() > 0:
await file_input.set_input_files(str(SAMPLE_DOC))
await asyncio.sleep(3)
await snap("Uploaded!", 3)
await asyncio.sleep(2)
await snap("KB with Docs", 3)
# 5. CREATE NEW CHAT
print("[5] Create Chat")
await page.goto(f"{FRONTEND_URL}/dashboard/chat/new", timeout=30000)
await asyncio.sleep(2)
await snap("New Chat", 2)
# Select KB with RADIO button
radio = page.locator('input[type="radio"]').first
if await radio.count() > 0:
await radio.click()
await asyncio.sleep(0.5)
await snap("KB Selected", 2)
# Fill title
title_input = page.locator('input[placeholder*="title" i], input[name="title"]')
if await title_input.count() > 0:
await title_input.first.fill("Product Questions")
await asyncio.sleep(0.3)
# Click Start Chat button
start_btn = page.locator('button:has-text("Start Chat"), button[type="submit"]')
if await start_btn.count() > 0:
await start_btn.first.click()
print(" Creating chat session...")
await asyncio.sleep(3)
await snap("Chat Created!", 3)
# 6. NOW ON CHAT PAGE - SEND MESSAGE
print("[6] Chat with AI")
await asyncio.sleep(3)
await snap("Chat Interface", 3)
# Find message input by placeholder
msg_input = page.locator('input[placeholder*="message" i]')
if await msg_input.count() > 0:
await msg_input.click()
await asyncio.sleep(0.3)
# Type question
q = "What are the key features of Info Naut?"
print(f" Asking: {q}")
await msg_input.fill(q)
await asyncio.sleep(0.5)
await snap("Question typed", 3)
# Send
send_btn = page.locator('button[type="submit"]')
if await send_btn.count() > 0:
await send_btn.click()
await snap("Sending...", 2)
# WAIT FOR AI RESPONSE
print(" Waiting for OpenAI response...")
await asyncio.sleep(15)
await snap("AI RESPONSE!", 6)
# Scroll
await page.evaluate("window.scrollTo(0, 9999)")
await asyncio.sleep(1)
await snap("Full Response", 4)
# FOLLOW UP
print(" Follow-up question...")
await asyncio.sleep(2)
# Re-find input after response
msg2 = page.locator('input[placeholder*="message" i]')
if await msg2.count() > 0:
await msg2.fill("How does document processing work?")
await asyncio.sleep(0.5)
await snap("Follow-up", 2)
send2 = page.locator('button[type="submit"]')
if await send2.count() > 0:
await send2.click()
print(" Waiting for 2nd response...")
await asyncio.sleep(12)
await snap("2nd Response!", 5)
else:
print(" Could not find message input")
await snap("Chat page", 3)
# 7. API KEYS
print("[7] API Keys")
await page.goto(f"{FRONTEND_URL}/dashboard/api-keys", timeout=30000)
await asyncio.sleep(1.5)
await snap("API Keys", 3)
# Create API key
create_key = page.locator('button:has-text("Create")')
if await create_key.count() > 0:
await create_key.first.click()
await asyncio.sleep(1)
await snap("Create Key", 2)
# 8. FINAL
print("[8] Done!")
await page.goto(f"{FRONTEND_URL}/dashboard", timeout=30000)
await asyncio.sleep(1)
await snap("Complete!", 3)
await browser.close()
print(f"\nFrames: {fc[0]}")
# CREATE GIF
print("\nCreating GIF...")
from PIL import Image
files = sorted(frames_dir.glob("f_*.png"))
frames = []
for f in files:
img = Image.open(f).resize((800, 450), Image.LANCZOS)
img = img.convert('P', palette=Image.ADAPTIVE, colors=256)
frames.append(img)
frames[0].save(GIF_PATH, save_all=True, append_images=frames[1:],
duration=280, loop=0, optimize=True)
sz = os.path.getsize(GIF_PATH) / (1024*1024)
print(f"GIF: {sz:.2f} MB ({len(frames)} frames)")
if sz > 5:
opt = [frames[i] for i in range(0, len(frames), 2)]
opt[0].save(GIF_PATH, save_all=True, append_images=opt[1:],
duration=560, loop=0, optimize=True)
print(f"Optimized: {os.path.getsize(GIF_PATH)/(1024*1024):.2f} MB")
shutil.rmtree(frames_dir)
print("\n" + "="*70)
print("SUCCESS!")
print("="*70)
if __name__ == "__main__":
asyncio.run(main())