Spaces:
Runtime error
Runtime error
deploy at 2024-08-06 15:09:58.948539
Browse files- Dockerfile +10 -0
- LICENSE +21 -0
- README.md +2 -10
- dinkan.html +503 -0
- expendables.py +488 -0
- favicon.ico +0 -0
- main.py +489 -0
- polling.py +89 -0
- requirements.txt +5 -0
- simple.py +64 -0
Dockerfile
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.10
|
| 2 |
+
WORKDIR /code
|
| 3 |
+
COPY --link --chown=1000 . .
|
| 4 |
+
RUN mkdir -p /tmp/cache/
|
| 5 |
+
RUN chmod a+rwx -R /tmp/cache/
|
| 6 |
+
ENV HF_HUB_CACHE=HF_HOME
|
| 7 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 8 |
+
|
| 9 |
+
ENV PYTHONUNBUFFERED=1 PORT=7860
|
| 10 |
+
CMD ["python", "main.py"]
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2024 Rajesh Radhakrishnan
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README.md
CHANGED
|
@@ -1,10 +1,2 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
emoji: 🚀
|
| 4 |
-
colorFrom: red
|
| 5 |
-
colorTo: purple
|
| 6 |
-
sdk: docker
|
| 7 |
-
pinned: false
|
| 8 |
-
---
|
| 9 |
-
|
| 10 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
| 1 |
+
# aitemplate
|
| 2 |
+
research on generic ai tool use, search and code intepreter tool
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dinkan.html
ADDED
|
@@ -0,0 +1,503 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Chat Copilot</title>
|
| 7 |
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
| 8 |
+
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.8.1/font/bootstrap-icons.min.css" rel="stylesheet">
|
| 9 |
+
|
| 10 |
+
<style>
|
| 11 |
+
body {
|
| 12 |
+
display: flex;
|
| 13 |
+
height: 100vh;
|
| 14 |
+
overflow: hidden;
|
| 15 |
+
}
|
| 16 |
+
#sidebar {
|
| 17 |
+
background-color: #f8f9fa;
|
| 18 |
+
padding: 10px;
|
| 19 |
+
overflow-y: auto;
|
| 20 |
+
height: 100vh;
|
| 21 |
+
}
|
| 22 |
+
#chat {
|
| 23 |
+
display: flex;
|
| 24 |
+
flex-direction: column;
|
| 25 |
+
height: 100vh;
|
| 26 |
+
overflow-y: hidden;
|
| 27 |
+
}
|
| 28 |
+
#chat-messages {
|
| 29 |
+
flex-grow: 1;
|
| 30 |
+
overflow-y: auto;
|
| 31 |
+
padding: 10px;
|
| 32 |
+
}
|
| 33 |
+
#chat-input {
|
| 34 |
+
padding: 10px;
|
| 35 |
+
border-top: 1px solid #e9ecef;
|
| 36 |
+
}
|
| 37 |
+
#documentsTab {
|
| 38 |
+
padding: 20px;
|
| 39 |
+
}
|
| 40 |
+
.file-upload {
|
| 41 |
+
display: none;
|
| 42 |
+
}
|
| 43 |
+
.file-icon {
|
| 44 |
+
width: 20px;
|
| 45 |
+
height: 20px;
|
| 46 |
+
}
|
| 47 |
+
.progress-bar {
|
| 48 |
+
width: 100%;
|
| 49 |
+
height: 100%;
|
| 50 |
+
background-color: #4caf50;
|
| 51 |
+
}
|
| 52 |
+
.container-fluid {
|
| 53 |
+
overflow-y: auto;
|
| 54 |
+
}
|
| 55 |
+
.form-label {
|
| 56 |
+
font-weight: bold;
|
| 57 |
+
}
|
| 58 |
+
.list-group-item {
|
| 59 |
+
cursor: pointer;
|
| 60 |
+
}
|
| 61 |
+
</style>
|
| 62 |
+
</head>
|
| 63 |
+
<body>
|
| 64 |
+
<div class="container-fluid">
|
| 65 |
+
<nav class="navbar navbar-expand-lg navbar-dark" style="background-color: #800080;">
|
| 66 |
+
<div class="container-fluid">
|
| 67 |
+
<a class="navbar-brand" href="#">Groqlet Expendables</a>
|
| 68 |
+
<div class="d-flex align-items-center">
|
| 69 |
+
<a class="nav-link text-white" href="#" style="margin-right: 10px;">
|
| 70 |
+
<i class="bi bi-plug"></i> Plugins
|
| 71 |
+
</a>
|
| 72 |
+
<img src="user-icon-url" alt="User Icon" class="rounded-circle" style="width: 30px; height: 30px;">
|
| 73 |
+
</div>
|
| 74 |
+
</div>
|
| 75 |
+
</nav>
|
| 76 |
+
<div class="row">
|
| 77 |
+
<!-- Sidebar -->
|
| 78 |
+
<div class="col-12 col-md-3" id="sidebar">
|
| 79 |
+
<div class="d-flex justify-content-between align-items-center mb-2">
|
| 80 |
+
<h4>Chat</h4>
|
| 81 |
+
<button class="btn btn-primary btn-sm" id="addChatBtn">+</button>
|
| 82 |
+
</div>
|
| 83 |
+
<ul class="list-group" id="chatList">
|
| 84 |
+
<!-- Dynamically populated agents list of chat items -->
|
| 85 |
+
<!-- <li class="list-group-item">
|
| 86 |
+
<div class="d-flex justify-content-between">
|
| 87 |
+
<span>Can you tell me a story?</span>
|
| 88 |
+
<small>11:10 PM</small>
|
| 89 |
+
</div>
|
| 90 |
+
</li> -->
|
| 91 |
+
|
| 92 |
+
</ul>
|
| 93 |
+
</div>
|
| 94 |
+
<!-- Context menu for renaming chat items -->
|
| 95 |
+
<div id="contextMenu" class="dropdown-menu" style="display:none; position:absolute;">
|
| 96 |
+
<a class="dropdown-item" href="#" id="renameItem">Rename</a>
|
| 97 |
+
</div>
|
| 98 |
+
<!-- Chat -->
|
| 99 |
+
<div class="col-12 col-md-9 d-flex flex-column" id="chat">
|
| 100 |
+
<ul class="nav nav-tabs">
|
| 101 |
+
<li class="nav-item">
|
| 102 |
+
<a class="nav-link active" data-bs-toggle="tab" href="#chatTab">Chat</a>
|
| 103 |
+
</li>
|
| 104 |
+
<li class="nav-item">
|
| 105 |
+
<a class="nav-link" data-bs-toggle="tab" href="#documentsTab">Documents</a>
|
| 106 |
+
</li>
|
| 107 |
+
<li class="nav-item">
|
| 108 |
+
<a class="nav-link" data-bs-toggle="tab" href="#plansTab">Plans</a>
|
| 109 |
+
</li>
|
| 110 |
+
<li class="nav-item">
|
| 111 |
+
<a class="nav-link" data-bs-toggle="tab" href="#personasTab">Personas</a>
|
| 112 |
+
</li>
|
| 113 |
+
</ul>
|
| 114 |
+
<div class="tab-content flex-grow-1">
|
| 115 |
+
<div class="tab-pane fade show active" id="chatTab">
|
| 116 |
+
<div id="chat-messages">
|
| 117 |
+
<div class="chat-message">
|
| 118 |
+
<strong>Copilot</strong>
|
| 119 |
+
<p>Hello, thank you for democratizing AI's productivity benefits with open source! How can I help you today?</p>
|
| 120 |
+
</div>
|
| 121 |
+
<div class="chat-message">
|
| 122 |
+
<strong>MB</strong>
|
| 123 |
+
<p>Can you tell me a story about a prince in a paragraph?</p>
|
| 124 |
+
</div>
|
| 125 |
+
</div>
|
| 126 |
+
<div id="chat-input" class="d-flex">
|
| 127 |
+
<input type="text" class="form-control me-2" placeholder="Type a message..." id="messageInput">
|
| 128 |
+
<button class="btn btn-primary" id="sendBtn">Send</button>
|
| 129 |
+
</div>
|
| 130 |
+
</div>
|
| 131 |
+
<div class="tab-pane fade" id="documentsTab">
|
| 132 |
+
<!-- Content for Documents tab -->
|
| 133 |
+
<div class="d-flex justify-content-between align-items-center mb-2">
|
| 134 |
+
<h4>Documents</h4>
|
| 135 |
+
<button class="btn btn-primary btn-sm" id="uploadBtn">Upload</button>
|
| 136 |
+
<input type="file" id="fileInput" class="file-upload">
|
| 137 |
+
</div>
|
| 138 |
+
<div class="d-flex mb-2">
|
| 139 |
+
<div class="form-check me-3">
|
| 140 |
+
<input class="form-check-input" type="radio" name="vectorDatabase" id="volatile" value="volatile">
|
| 141 |
+
<label class="form-check-label" for="volatile">Volatile</label>
|
| 142 |
+
</div>
|
| 143 |
+
<div class="form-check me-3">
|
| 144 |
+
<input class="form-check-input" type="radio" name="vectorDatabase" id="textFile" value="textFile" checked>
|
| 145 |
+
<label class="form-check-label" for="textFile">TextFile</label>
|
| 146 |
+
</div>
|
| 147 |
+
<div class="form-check me-3">
|
| 148 |
+
<input class="form-check-input" type="radio" name="vectorDatabase" id="qdrant" value="qdrant">
|
| 149 |
+
<label class="form-check-label" for="qdrant">Qdrant</label>
|
| 150 |
+
</div>
|
| 151 |
+
<div class="form-check">
|
| 152 |
+
<input class="form-check-input" type="radio" name="vectorDatabase" id="llamaindexSearch" value="llamaindexSearch">
|
| 153 |
+
<label class="form-check-label" for="llamaindexSearch">llamaindex Search</label>
|
| 154 |
+
</div>
|
| 155 |
+
</div>
|
| 156 |
+
<table class="table">
|
| 157 |
+
<thead>
|
| 158 |
+
<tr>
|
| 159 |
+
<th>Name</th>
|
| 160 |
+
<th>Created on</th>
|
| 161 |
+
<th>Size (bytes)</th>
|
| 162 |
+
<th>Access</th>
|
| 163 |
+
<th>Progress</th>
|
| 164 |
+
</tr>
|
| 165 |
+
</thead>
|
| 166 |
+
<tbody id="fileTable">
|
| 167 |
+
<tr>
|
| 168 |
+
<td><i class="bi bi-file-earmark-text file-icon"></i> reconciliation.txt</td>
|
| 169 |
+
<td>9:38 am</td>
|
| 170 |
+
<td>30,079</td>
|
| 171 |
+
<td>This chat</td>
|
| 172 |
+
<td><div class="progress"><div class="progress-bar"></div></div></td>
|
| 173 |
+
</tr>
|
| 174 |
+
</tbody>
|
| 175 |
+
</table>
|
| 176 |
+
</div>
|
| 177 |
+
<div class="tab-pane fade" id="plansTab">
|
| 178 |
+
<!-- Content for Plans tab -->
|
| 179 |
+
<table class="table">
|
| 180 |
+
<thead>
|
| 181 |
+
<tr>
|
| 182 |
+
<th>Goal</th>
|
| 183 |
+
<th>Created on</th>
|
| 184 |
+
<th>Token Count</th>
|
| 185 |
+
</tr>
|
| 186 |
+
</thead>
|
| 187 |
+
<tbody id="planTable">
|
| 188 |
+
<tr>
|
| 189 |
+
<td>askQuestions</td>
|
| 190 |
+
<td>9:38 am</td>
|
| 191 |
+
<td>30,079</td>
|
| 192 |
+
</tr>
|
| 193 |
+
</tbody>
|
| 194 |
+
</table>
|
| 195 |
+
</div>
|
| 196 |
+
<div class="tab-pane fade" id="personasTab">
|
| 197 |
+
<!-- Content for Personas tab -->
|
| 198 |
+
<div class="container-fluid p-3">
|
| 199 |
+
<h4>Persona</h4>
|
| 200 |
+
<div class="mb-3">
|
| 201 |
+
<label for="agentNameInput" class="form-label">Agent Name</label>
|
| 202 |
+
<input type="text" class="form-control" id="agentNameInput" placeholder="Enter your agent's name...">
|
| 203 |
+
</div>
|
| 204 |
+
<div class="mb-3">
|
| 205 |
+
<label for="metaPromptInput" class="form-label">Meta Prompt</label>
|
| 206 |
+
<textarea class="form-control" id="metaPromptInput" rows="3" placeholder="Enter your Meta Prompt..."></textarea>
|
| 207 |
+
</div>
|
| 208 |
+
<div class="mb-3">
|
| 209 |
+
<label for="prefillInput" class="form-label">Prefill</label>
|
| 210 |
+
<textarea class="form-control" id="prefillInput" rows="3" placeholder="Enter agent's prefill..."></textarea>
|
| 211 |
+
</div>
|
| 212 |
+
<div class="d-flex justify-content-end">
|
| 213 |
+
<button class="btn btn-primary" id="savePlanBtn">Save</button>
|
| 214 |
+
</div>
|
| 215 |
+
<hr>
|
| 216 |
+
<h5>Saved Plans</h5>
|
| 217 |
+
<ul class="list-group" id="savedPlansList">
|
| 218 |
+
<!-- Dynamically populated list of saved plans -->
|
| 219 |
+
</ul>
|
| 220 |
+
</div>
|
| 221 |
+
</div>
|
| 222 |
+
</div>
|
| 223 |
+
</div>
|
| 224 |
+
|
| 225 |
+
</div>
|
| 226 |
+
</div>
|
| 227 |
+
|
| 228 |
+
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
| 229 |
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
|
| 230 |
+
<script>
|
| 231 |
+
let agents = [
|
| 232 |
+
{
|
| 233 |
+
"Persona": {
|
| 234 |
+
"agentname": "dinkan-1",
|
| 235 |
+
"metaprompt": "you are a helpful assistant",
|
| 236 |
+
"prefill": "helps me with financial Reconciliation",
|
| 237 |
+
"tooluse": "true",
|
| 238 |
+
"filesearch": "true",
|
| 239 |
+
"codeinterpreter": "true"
|
| 240 |
+
},
|
| 241 |
+
"Plans": [
|
| 242 |
+
{ "name": "askquestion", "createon": "06/8/2024", "tokencount": "2048" }
|
| 243 |
+
],
|
| 244 |
+
"Documents": [
|
| 245 |
+
{ "file": "./reconciliation.txt", "createon": "06/8/2024", "size": "30,079", "Access": "private", "progress": "success" },
|
| 246 |
+
{ "file": "./design.pdf", "createon": "07/8/2024", "size": "30,079", "Access": "public", "progress": "error" }
|
| 247 |
+
],
|
| 248 |
+
"Chat": [
|
| 249 |
+
{"role": "system", "content":"Hello, thank you for democratizing AI's productivity benefits with open source! How can I help you today?"},
|
| 250 |
+
{ "role": "assistant", "content": "what is the capital of India" },
|
| 251 |
+
{ "role": "user", "content": "New Delhi is the capital of India" }
|
| 252 |
+
]
|
| 253 |
+
},
|
| 254 |
+
{
|
| 255 |
+
"Persona": {
|
| 256 |
+
"agentname": "dinkan-2",
|
| 257 |
+
"metaprompt": "you are a helpful assistant",
|
| 258 |
+
"prefill": "helps me with financial Reconciliation",
|
| 259 |
+
"tooluse": "true",
|
| 260 |
+
"filesearch": "false",
|
| 261 |
+
"codeinterpreter": "false"
|
| 262 |
+
},
|
| 263 |
+
"Plans": [
|
| 264 |
+
{ "name": "calculate", "createon": "07/8/2024", "tokencount": "1024" }
|
| 265 |
+
],
|
| 266 |
+
"Documents": [
|
| 267 |
+
{ "file": "./design.txt", "createon": "08/8/2024", "size": "30,079", "Access": "private", "progress": "success" },
|
| 268 |
+
{ "file": "./design.pdf", "createon": "09/8/2024", "size": "30,079", "Access": "public", "progress": "error" }
|
| 269 |
+
],
|
| 270 |
+
"Chat": [
|
| 271 |
+
{"role": "system", "content":"Hello, thank you for democratizing AI's productivity benefits with open source! How can I help you today?"},
|
| 272 |
+
{ "role": "assistant", "content": "what is the capital of Kerala" },
|
| 273 |
+
{ "role": "user", "content": "Trivandrum is the capital of India" }
|
| 274 |
+
]
|
| 275 |
+
}
|
| 276 |
+
];
|
| 277 |
+
|
| 278 |
+
let selectedAgentIndex = -1;
|
| 279 |
+
|
| 280 |
+
function populateTabs() {
|
| 281 |
+
if (selectedAgentIndex >= 0) {
|
| 282 |
+
const selectedAgent = agents[selectedAgentIndex];
|
| 283 |
+
|
| 284 |
+
// Populate Personas tab
|
| 285 |
+
const agentNameInput = document.getElementById('agentNameInput');
|
| 286 |
+
const metaPromptInput = document.getElementById('metaPromptInput');
|
| 287 |
+
const prefillInput = document.getElementById('prefillInput');
|
| 288 |
+
|
| 289 |
+
agentNameInput.value = agents[selectedAgentIndex].Persona.agentname;
|
| 290 |
+
metaPromptInput.value = agents[selectedAgentIndex].Persona.metaprompt;
|
| 291 |
+
prefillInput.value = agents[selectedAgentIndex].Persona.prefill;
|
| 292 |
+
|
| 293 |
+
// Populate Plans tab
|
| 294 |
+
// Clear and repopulate the plans table or list with selectedAgent.Plans
|
| 295 |
+
const planTable = document.getElementById('planTable');
|
| 296 |
+
planTable.innerHTML = '';
|
| 297 |
+
agents[selectedAgentIndex].Plans.forEach(plan => {
|
| 298 |
+
const newRow = `<tr>
|
| 299 |
+
<td>${plan.name}</td>
|
| 300 |
+
<td>${plan.createon}</td>
|
| 301 |
+
<td>${plan.tokencount}</td>
|
| 302 |
+
</tr>`;
|
| 303 |
+
planTable.insertAdjacentHTML('beforeend', newRow);
|
| 304 |
+
});
|
| 305 |
+
// Populate Documents tab
|
| 306 |
+
// Clear and repopulate the documents table with selectedAgent.Documents
|
| 307 |
+
const fileTable = document.getElementById('fileTable');
|
| 308 |
+
fileTable.innerHTML = '';
|
| 309 |
+
agents[selectedAgentIndex].Documents.forEach(doc => {
|
| 310 |
+
const newRow = `<tr>
|
| 311 |
+
<td><i class="bi bi-file-earmark-text file-icon"></i> ${doc.file}</td>
|
| 312 |
+
<td>${doc.createon}</td>
|
| 313 |
+
<td>${doc.size}</td>
|
| 314 |
+
<td>${doc.Access}</td>
|
| 315 |
+
<td><div class="progress"><div class="progress-bar"></div></div></td>
|
| 316 |
+
</tr>`;
|
| 317 |
+
fileTable.insertAdjacentHTML('beforeend', newRow);
|
| 318 |
+
});
|
| 319 |
+
// Display initial messages
|
| 320 |
+
//displayMessages();
|
| 321 |
+
}
|
| 322 |
+
}
|
| 323 |
+
|
| 324 |
+
function renderChatList() {
|
| 325 |
+
const chatList = document.getElementById('chatList');
|
| 326 |
+
chatList.innerHTML = ''; // Clear the existing list
|
| 327 |
+
|
| 328 |
+
agents.forEach((agent, index) => {
|
| 329 |
+
const newItem = document.createElement('li');
|
| 330 |
+
newItem.className = 'list-group-item';
|
| 331 |
+
newItem.innerHTML = `<div class="d-flex justify-content-between">
|
| 332 |
+
<span>${agent.Persona.agentname}</span>
|
| 333 |
+
<small>${new Date().toLocaleTimeString()}</small>
|
| 334 |
+
</div>`;
|
| 335 |
+
newItem.setAttribute('data-index', index);
|
| 336 |
+
newItem.setAttribute('data-messages', JSON.stringify(agent.Chat));
|
| 337 |
+
newItem.addEventListener('click', function() {
|
| 338 |
+
selectedAgentIndex = parseInt(this.getAttribute('data-index'));
|
| 339 |
+
displayMessages();
|
| 340 |
+
populateTabs();
|
| 341 |
+
});
|
| 342 |
+
newItem.addEventListener('contextmenu', function(e) {
|
| 343 |
+
e.preventDefault();
|
| 344 |
+
showContextMenu(e, newItem, index);
|
| 345 |
+
});
|
| 346 |
+
chatList.appendChild(newItem);
|
| 347 |
+
});
|
| 348 |
+
}
|
| 349 |
+
// Event listener for add chat button - Sidebar
|
| 350 |
+
document.getElementById('addChatBtn').addEventListener('click', function() {
|
| 351 |
+
var chatList = document.getElementById('chatList');
|
| 352 |
+
var newItem = document.createElement('li');
|
| 353 |
+
newItem.className = 'list-group-item';
|
| 354 |
+
newItem.innerHTML = `<div class="d-flex justify-content-between">
|
| 355 |
+
<span>New Agent</span>
|
| 356 |
+
<small>${new Date().toLocaleTimeString()}</small>
|
| 357 |
+
</div>`;
|
| 358 |
+
newItem.setAttribute('data-messages', JSON.stringify([]));
|
| 359 |
+
chatList.appendChild(newItem);
|
| 360 |
+
|
| 361 |
+
// Add new agent to agents array
|
| 362 |
+
var newAgent = {
|
| 363 |
+
"Persona": {
|
| 364 |
+
"agentname": `agent-${Date.now()}`,
|
| 365 |
+
"metaprompt": "you are a helpful assistant",
|
| 366 |
+
"prefill": "helps me with financial Reconciliation",
|
| 367 |
+
"tooluse": "true",
|
| 368 |
+
"filesearch": "false",
|
| 369 |
+
"codeinterpreter": "false"
|
| 370 |
+
},
|
| 371 |
+
"Plans": [],
|
| 372 |
+
"Documents": [],
|
| 373 |
+
"Chat": []
|
| 374 |
+
};
|
| 375 |
+
agents.push(newAgent);
|
| 376 |
+
renderChatList();
|
| 377 |
+
});
|
| 378 |
+
|
| 379 |
+
// Show context menu
|
| 380 |
+
function showContextMenu(event, listItem) {
|
| 381 |
+
var contextMenu = document.getElementById('contextMenu');
|
| 382 |
+
contextMenu.style.display = 'block';
|
| 383 |
+
contextMenu.style.left = event.pageX + 'px';
|
| 384 |
+
contextMenu.style.top = event.pageY + 'px';
|
| 385 |
+
|
| 386 |
+
document.getElementById('renameItem').onclick = function() {
|
| 387 |
+
var newName = prompt("Enter new name:", listItem.querySelector('span').textContent);
|
| 388 |
+
if (newName) {
|
| 389 |
+
listItem.querySelector('span').textContent = newName;
|
| 390 |
+
//write a code to update the agent name in agents array
|
| 391 |
+
agents[selectedAgentIndex].Persona.agentname = newName;
|
| 392 |
+
}
|
| 393 |
+
contextMenu.style.display = 'none';
|
| 394 |
+
};
|
| 395 |
+
|
| 396 |
+
document.addEventListener('click', function() {
|
| 397 |
+
contextMenu.style.display = 'none';
|
| 398 |
+
}, { once: true });
|
| 399 |
+
}
|
| 400 |
+
|
| 401 |
+
// Event listener for existing items
|
| 402 |
+
document.querySelectorAll('#chatList .list-group-item').forEach(item => {
|
| 403 |
+
item.addEventListener('contextmenu', function(e) {
|
| 404 |
+
e.preventDefault();
|
| 405 |
+
showContextMenu(e, item);
|
| 406 |
+
});
|
| 407 |
+
});
|
| 408 |
+
// Function to display messages
|
| 409 |
+
function displayMessages() {
|
| 410 |
+
const chatMessages = document.getElementById('chat-messages');
|
| 411 |
+
chatMessages.innerHTML = '';
|
| 412 |
+
agents[selectedAgentIndex].Chat.forEach(msg => {
|
| 413 |
+
const messageElement = document.createElement('div');
|
| 414 |
+
messageElement.classList.add('chat-message');
|
| 415 |
+
messageElement.innerHTML = `<strong>${msg.role}</strong><p>${msg.content}</p>`;
|
| 416 |
+
chatMessages.appendChild(messageElement);
|
| 417 |
+
});
|
| 418 |
+
}
|
| 419 |
+
|
| 420 |
+
// Event listener for sidebar items
|
| 421 |
+
document.querySelectorAll('#chatList .list-group-item').forEach(item => {
|
| 422 |
+
item.addEventListener('click', function() {
|
| 423 |
+
const newMessages = JSON.parse(this.getAttribute('data-messages'));
|
| 424 |
+
messages = [...newMessages];
|
| 425 |
+
displayMessages();
|
| 426 |
+
});
|
| 427 |
+
});
|
| 428 |
+
|
| 429 |
+
// Event listener for send button
|
| 430 |
+
document.getElementById('sendBtn').addEventListener('click', function() {
|
| 431 |
+
const input = document.getElementById('messageInput');
|
| 432 |
+
const userMessage = input.value;
|
| 433 |
+
if (userMessage) {
|
| 434 |
+
agents[selectedAgentIndex].Chat.push({ role: 'MB', content: userMessage });
|
| 435 |
+
if (userMessage.toLowerCase() === 'what is the capital of india') {
|
| 436 |
+
agents[0].Chat.push({ role: 'Copilot', content: 'New Delhi is the capital of India' });
|
| 437 |
+
}
|
| 438 |
+
displayMessages();
|
| 439 |
+
input.value = '';
|
| 440 |
+
}
|
| 441 |
+
});
|
| 442 |
+
|
| 443 |
+
// Event listener for upload button
|
| 444 |
+
document.getElementById('uploadBtn').addEventListener('click', function() {
|
| 445 |
+
document.getElementById('fileInput').click();
|
| 446 |
+
});
|
| 447 |
+
|
| 448 |
+
// Event listener for file input - Documents Tab
|
| 449 |
+
document.getElementById('fileInput').addEventListener('change', function(event) {
|
| 450 |
+
const file = event.target.files[0];
|
| 451 |
+
if (file) {
|
| 452 |
+
const newRow = `<tr>
|
| 453 |
+
<td><i class="bi bi-file-earmark-text file-icon"></i> ${file.name}</td>
|
| 454 |
+
<td>${new Date().toLocaleTimeString()}</td>
|
| 455 |
+
<td>${file.size}</td>
|
| 456 |
+
<td>This chat</td>
|
| 457 |
+
<td><div class="progress"><div class="progress-bar"></div></div></td>
|
| 458 |
+
</tr>`;
|
| 459 |
+
document.getElementById('fileTable').insertAdjacentHTML('beforeend', newRow);
|
| 460 |
+
}
|
| 461 |
+
});
|
| 462 |
+
|
| 463 |
+
// Event listener for save button - Personas Tab
|
| 464 |
+
document.getElementById('savePlanBtn').addEventListener('click', function() {
|
| 465 |
+
const agentname = document.getElementById('agentNameInput').value;
|
| 466 |
+
const metaprompt = document.getElementById('metaPromptInput').value;
|
| 467 |
+
const prefill = document.getElementById('prefillInput').value;
|
| 468 |
+
|
| 469 |
+
const plan = {
|
| 470 |
+
agentname,
|
| 471 |
+
metaprompt,
|
| 472 |
+
prefill
|
| 473 |
+
};
|
| 474 |
+
|
| 475 |
+
const savedPlansList = document.getElementById('savedPlansList');
|
| 476 |
+
const planItem = document.createElement('li');
|
| 477 |
+
planItem.classList.add('list-group-item');
|
| 478 |
+
planItem.textContent = `Agent Name: ${agentname}`;
|
| 479 |
+
planItem.addEventListener('click', function() {
|
| 480 |
+
alert(`Meta Prompt: ${plan.metaprompt}\nPrefill: ${plan.prefill}`);
|
| 481 |
+
});
|
| 482 |
+
|
| 483 |
+
savedPlansList.appendChild(planItem);
|
| 484 |
+
|
| 485 |
+
// Clear the inputs after saving
|
| 486 |
+
document.getElementById('agentNameInput').value = '';
|
| 487 |
+
document.getElementById('metaPromptInput').value = '';
|
| 488 |
+
document.getElementById('prefillInput').value = '';
|
| 489 |
+
});
|
| 490 |
+
|
| 491 |
+
|
| 492 |
+
|
| 493 |
+
// Initial rendering of the chat list
|
| 494 |
+
renderChatList();
|
| 495 |
+
|
| 496 |
+
// Populate tabs initially (if needed)
|
| 497 |
+
populateTabs();
|
| 498 |
+
|
| 499 |
+
|
| 500 |
+
|
| 501 |
+
</script>
|
| 502 |
+
</body>
|
| 503 |
+
</html>
|
expendables.py
ADDED
|
@@ -0,0 +1,488 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
from fasthtml.common import *
|
| 3 |
+
|
| 4 |
+
bootstraplink = Link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css", integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC", crossorigin="anonymous")
|
| 5 |
+
fontlink = Link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.8.1/font/bootstrap-icons.min.css")
|
| 6 |
+
favicon = Link(rel="icon", type="image/x-icon", href="https://raw.githubusercontent.com/rajeshradhakrishnanmvk/aitemplate/main/favicon.ico")
|
| 7 |
+
|
| 8 |
+
title = Title("Groqlet Expendables")
|
| 9 |
+
css = Style("""body {
|
| 10 |
+
display: flex;
|
| 11 |
+
height: 100vh;
|
| 12 |
+
overflow: hidden;
|
| 13 |
+
}
|
| 14 |
+
#sidebar {
|
| 15 |
+
background-color: #f8f9fa;
|
| 16 |
+
padding: 10px;
|
| 17 |
+
overflow-y: auto;
|
| 18 |
+
height: 100vh;
|
| 19 |
+
}
|
| 20 |
+
#chat {
|
| 21 |
+
display: flex;
|
| 22 |
+
flex-direction: column;
|
| 23 |
+
height: 100vh;
|
| 24 |
+
overflow-y: hidden;
|
| 25 |
+
}
|
| 26 |
+
#chat-messages {
|
| 27 |
+
flex-grow: 1;
|
| 28 |
+
overflow-y: auto;
|
| 29 |
+
padding: 10px;
|
| 30 |
+
}
|
| 31 |
+
#chat-input {
|
| 32 |
+
padding: 10px;
|
| 33 |
+
border-top: 1px solid #e9ecef;
|
| 34 |
+
}
|
| 35 |
+
#documentsTab {
|
| 36 |
+
padding: 20px;
|
| 37 |
+
}
|
| 38 |
+
.file-upload {
|
| 39 |
+
display: none;
|
| 40 |
+
}
|
| 41 |
+
.file-icon {
|
| 42 |
+
width: 20px;
|
| 43 |
+
height: 20px;
|
| 44 |
+
}
|
| 45 |
+
.progress-bar {
|
| 46 |
+
width: 100%;
|
| 47 |
+
height: 100%;
|
| 48 |
+
background-color: #4caf50;
|
| 49 |
+
}
|
| 50 |
+
.container-fluid {
|
| 51 |
+
overflow-y: auto;
|
| 52 |
+
}
|
| 53 |
+
.form-label {
|
| 54 |
+
font-weight: bold;
|
| 55 |
+
}
|
| 56 |
+
.list-group-item {
|
| 57 |
+
cursor: pointer;
|
| 58 |
+
}""")
|
| 59 |
+
|
| 60 |
+
app = FastHTML(hdrs=(title,favicon,bootstraplink, fontlink,css))
|
| 61 |
+
|
| 62 |
+
data = json.dumps([
|
| 63 |
+
{
|
| 64 |
+
"Persona": {
|
| 65 |
+
"agentname": "dinkan-1",
|
| 66 |
+
"metaprompt": "you are a helpful assistant",
|
| 67 |
+
"prefill": "helps me with financial Reconciliation",
|
| 68 |
+
"tooluse": "true",
|
| 69 |
+
"filesearch": "true",
|
| 70 |
+
"codeinterpreter": "true"
|
| 71 |
+
},
|
| 72 |
+
"Plans": [
|
| 73 |
+
{ "name": "askquestion", "createon": "06/8/2024", "tokencount": "2048" }
|
| 74 |
+
],
|
| 75 |
+
"Documents": [
|
| 76 |
+
{ "file": "./reconciliation.txt", "createon": "06/8/2024", "size": "30,079", "Access": "private", "progress": "success" },
|
| 77 |
+
{ "file": "./design.pdf", "createon": "07/8/2024", "size": "30,079", "Access": "public", "progress": "error" }
|
| 78 |
+
],
|
| 79 |
+
"Chat": [
|
| 80 |
+
{"role": "system", "content":"Hello, thank you for democratizing AI's productivity benefits with open source! How can I help you today?"},
|
| 81 |
+
{ "role": "assistant", "content": "what is the capital of India" },
|
| 82 |
+
{ "role": "user", "content": "New Delhi is the capital of India" }
|
| 83 |
+
]
|
| 84 |
+
},
|
| 85 |
+
{
|
| 86 |
+
"Persona": {
|
| 87 |
+
"agentname": "dinkan-2",
|
| 88 |
+
"metaprompt": "you are a helpful assistant",
|
| 89 |
+
"prefill": "helps me with financial Reconciliation",
|
| 90 |
+
"tooluse": "true",
|
| 91 |
+
"filesearch": "false",
|
| 92 |
+
"codeinterpreter": "false"
|
| 93 |
+
},
|
| 94 |
+
"Plans": [
|
| 95 |
+
{ "name": "calculate", "createon": "07/8/2024", "tokencount": "1024" }
|
| 96 |
+
],
|
| 97 |
+
"Documents": [
|
| 98 |
+
{ "file": "./design.txt", "createon": "08/8/2024", "size": "30,079", "Access": "private", "progress": "success" },
|
| 99 |
+
{ "file": "./design.pdf", "createon": "09/8/2024", "size": "30,079", "Access": "public", "progress": "error" }
|
| 100 |
+
],
|
| 101 |
+
"Chat": [
|
| 102 |
+
{"role": "system", "content":"Hello, thank you for democratizing AI's productivity benefits with open source! How can I help you today?"},
|
| 103 |
+
{ "role": "assistant", "content": "what is the capital of Kerala" },
|
| 104 |
+
{ "role": "user", "content": "Trivandrum is the capital of India" }
|
| 105 |
+
]
|
| 106 |
+
}
|
| 107 |
+
])
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
@app.route("/")
|
| 111 |
+
def get():
|
| 112 |
+
page = (Div(
|
| 113 |
+
Nav(
|
| 114 |
+
Div(
|
| 115 |
+
A("Groqlet Expendables", cls="navbar-brand", href="#"),
|
| 116 |
+
Div(
|
| 117 |
+
A(
|
| 118 |
+
I(cls="bi bi-plug"),
|
| 119 |
+
"Plugins", cls="nav-link text-white", href="#", style="margin-right: 10px;"),
|
| 120 |
+
A(
|
| 121 |
+
I(cls="bi bi-gear"),
|
| 122 |
+
"Settings", cls="nav-link text-white", href="#", style="margin-right: 10px;"),
|
| 123 |
+
|
| 124 |
+
Img(cls="rounded-circle", src="https://media.licdn.com/dms/image/C4D03AQHwjVMduekRjw/profile-displayphoto-shrink_100_100/0/1516794061157?e=1728518400&v=beta&t=JwjApmMV83LH01mtr8jUhh5wayHWFqPEhneLEU10HRI", alt="User Icon", style="width: 30px; height: 30px;")
|
| 125 |
+
,cls="d-flex align-items-center")
|
| 126 |
+
,cls="container-fluid")
|
| 127 |
+
,cls="navbar navbar-expand-lg navbar-dark",style="background-color: #800080;"),
|
| 128 |
+
Div(
|
| 129 |
+
Div(
|
| 130 |
+
Div(
|
| 131 |
+
H4("Agents"),
|
| 132 |
+
Button("+", cls="btn btn-primary btn-sm", id="addChatBtn")
|
| 133 |
+
, cls="d-flex justify-content-between align-items-center mb-2"),
|
| 134 |
+
Ul(
|
| 135 |
+
Li(
|
| 136 |
+
Div(
|
| 137 |
+
Span("Can you tell me a story?"),
|
| 138 |
+
Small("11:10 PM")
|
| 139 |
+
, cls="d-flex justify-content-between")
|
| 140 |
+
, cls="list-group-item")
|
| 141 |
+
, cls="list-group", id="chatList")
|
| 142 |
+
, cls="col-12 col-md-3", id="sidebar"),
|
| 143 |
+
Div(
|
| 144 |
+
A("Rename", cls="dropdown-item", href="#", id="renameItem")
|
| 145 |
+
,id="contextMenu", cls="dropdown-menu", style="display:none; position:absolute;"),
|
| 146 |
+
Div(
|
| 147 |
+
Ul(
|
| 148 |
+
Li(
|
| 149 |
+
A("Chat", cls="nav-link active", data_bs_toggle="tab", href="#chatTab")
|
| 150 |
+
, cls="nav-item"),
|
| 151 |
+
Li(
|
| 152 |
+
A("Documents", cls="nav-link", data_bs_toggle="tab", href="#documentsTab")
|
| 153 |
+
, cls="nav-item"),
|
| 154 |
+
Li(
|
| 155 |
+
A("Plans", cls="nav-link", data_bs_toggle="tab", href="#plansTab")
|
| 156 |
+
, cls="nav-item"),
|
| 157 |
+
Li(
|
| 158 |
+
A("Personas", cls="nav-link", data_bs_toggle="tab", href="#personasTab")
|
| 159 |
+
, cls="nav-item")
|
| 160 |
+
, cls="nav nav-tabs"),
|
| 161 |
+
Div(
|
| 162 |
+
Div(
|
| 163 |
+
Div(
|
| 164 |
+
Div(
|
| 165 |
+
Strong("Copilot"),
|
| 166 |
+
P("Hello, thank you for democratizing AI's productivity benefits with open source! How can I help you today?")
|
| 167 |
+
, cls="chat-message"),
|
| 168 |
+
Div(
|
| 169 |
+
Strong("MB"),
|
| 170 |
+
P("Can you tell me a story about a prince in a paragraph?")
|
| 171 |
+
, cls="chat-message")
|
| 172 |
+
, id="chat-messages"),
|
| 173 |
+
Div(
|
| 174 |
+
Input(type="text", cls="form-control me-2", placeholder="Type a message...", id="messageInput"),
|
| 175 |
+
Button("Send", cls="btn btn-primary", id="sendBtn")
|
| 176 |
+
, id="chat-input", cls="d-flex")
|
| 177 |
+
, cls="tab-pane fade show active", id="chatTab"),
|
| 178 |
+
Div(
|
| 179 |
+
Div(
|
| 180 |
+
H4("Documents"),
|
| 181 |
+
Button("Upload", cls="btn btn-primary btn-sm", id="uploadBtn"),
|
| 182 |
+
Input(type="file", id="fileInput", cls="file-upload")
|
| 183 |
+
, cls="d-flex justify-content-between align-items-center mb-2"),
|
| 184 |
+
Div(
|
| 185 |
+
Div(
|
| 186 |
+
Input(cls="form-check-input", type="radio", name="vectorDatabase", id="volatile", value="volatile"),
|
| 187 |
+
Label("Volatile", cls="form-check-label", _for="volatile")
|
| 188 |
+
, cls="form-check me-3"),
|
| 189 |
+
Div(
|
| 190 |
+
Input(cls="form-check-input", type="radio", name="vectorDatabase", id="textFile", value="textFile", checked=1),
|
| 191 |
+
Label("TextFile", cls="form-check-label", _for="textFile")
|
| 192 |
+
, cls="form-check me-3"),
|
| 193 |
+
Div(
|
| 194 |
+
Input(cls="form-check-input", type="radio", name="vectorDatabase", id="qdrant", value="qdrant"),
|
| 195 |
+
Label( "Qdrant", cls="form-check-label", _for="qdrant")
|
| 196 |
+
, cls="form-check me-3"),
|
| 197 |
+
Div(
|
| 198 |
+
Input(cls="form-check-input", type="radio", name="vectorDatabase", id="llamaindexSearch", value="llamaindexSearch"),
|
| 199 |
+
Label("llamaindex Search", cls="form-check-label", _for="llamaindexSearch")
|
| 200 |
+
, cls="form-check me-3")
|
| 201 |
+
,cls="d-flex mb-2"),
|
| 202 |
+
Table(
|
| 203 |
+
Thead(),
|
| 204 |
+
Tr(
|
| 205 |
+
Th("Name"),
|
| 206 |
+
Th("Created on"),
|
| 207 |
+
Th("Size (bytes)"),
|
| 208 |
+
Th("Access"),
|
| 209 |
+
Th("Progress")),
|
| 210 |
+
Tbody(
|
| 211 |
+
Tr(
|
| 212 |
+
Td(I(cls="bi bi-file-earmark-text file-icon"), " reconciliation.txt"),
|
| 213 |
+
Td("9:38 am"),
|
| 214 |
+
Td("30,079"),
|
| 215 |
+
Td("This chat"),
|
| 216 |
+
Td(Div(cls="progress"),Div(cls="progress-bar"))),id="fileTable"),cls="table")
|
| 217 |
+
,cls="tab-pane fade", id="documentsTab"),
|
| 218 |
+
Div(
|
| 219 |
+
Table(
|
| 220 |
+
Thead(),
|
| 221 |
+
Tr(
|
| 222 |
+
Th("Goal"),
|
| 223 |
+
Th("Created on"),
|
| 224 |
+
Th("Token Count")),
|
| 225 |
+
Tbody(id="planTable"),
|
| 226 |
+
Tr(
|
| 227 |
+
Td("askQuestions"),
|
| 228 |
+
Td("9:38 am"),
|
| 229 |
+
Td("30,079")),cls="table")
|
| 230 |
+
, cls="tab-pane fade", id="plansTab"),
|
| 231 |
+
Div(
|
| 232 |
+
Div(
|
| 233 |
+
H4("Persona"),
|
| 234 |
+
Div(
|
| 235 |
+
Label("Agent Name", cls="form-label", _for="agentNameInput"),
|
| 236 |
+
Input(type="text", cls="form-control", id="agentNameInput", placeholder="Enter your agent's name...")
|
| 237 |
+
, cls="mb-3"),
|
| 238 |
+
Div(
|
| 239 |
+
Label("Meta Prompt", cls="form-label", _for="metaPromptInput"),
|
| 240 |
+
Textarea(cls="form-control", id="metaPromptInput", rows="3", placeholder="Enter your Meta Prompt...")
|
| 241 |
+
, cls="mb-3"),
|
| 242 |
+
Div(
|
| 243 |
+
Label("Prefill", cls="form-label", _for="prefillInput"),
|
| 244 |
+
Textarea(cls="form-control", id="prefillInput", rows="3", placeholder="Enter agent's prefill...")
|
| 245 |
+
, cls="mb-3"),
|
| 246 |
+
Div(
|
| 247 |
+
Button("Save", cls="btn btn-primary", id="savePlanBtn")
|
| 248 |
+
, cls="d-flex justify-content-end"),
|
| 249 |
+
Hr(),
|
| 250 |
+
H5("Saved Plans"),
|
| 251 |
+
Ul(cls="list-group", id="savedPlansList")
|
| 252 |
+
, cls="container-fluid p-3")
|
| 253 |
+
, cls="tab-pane fade", id="personasTab")
|
| 254 |
+
|
| 255 |
+
, cls="tab-content flex-grow-1")
|
| 256 |
+
, cls="col-12 col-md-9 d-flex flex-column", id="chat")
|
| 257 |
+
, cls="row")
|
| 258 |
+
,cls="container-fluid"),
|
| 259 |
+
|
| 260 |
+
Script(src="https://code.jquery.com/jquery-3.6.0.min.js"),
|
| 261 |
+
Script(src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js", integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p",crossorigin="anonymous"),
|
| 262 |
+
Script(f"let agents = {data};"),
|
| 263 |
+
Script("""
|
| 264 |
+
let selectedAgentIndex = -1;
|
| 265 |
+
|
| 266 |
+
function populateTabs() {
|
| 267 |
+
if (selectedAgentIndex >= 0) {
|
| 268 |
+
const selectedAgent = agents[selectedAgentIndex];
|
| 269 |
+
|
| 270 |
+
// Populate Personas tab
|
| 271 |
+
const agentNameInput = document.getElementById('agentNameInput');
|
| 272 |
+
const metaPromptInput = document.getElementById('metaPromptInput');
|
| 273 |
+
const prefillInput = document.getElementById('prefillInput');
|
| 274 |
+
|
| 275 |
+
agentNameInput.value = agents[selectedAgentIndex].Persona.agentname;
|
| 276 |
+
metaPromptInput.value = agents[selectedAgentIndex].Persona.metaprompt;
|
| 277 |
+
prefillInput.value = agents[selectedAgentIndex].Persona.prefill;
|
| 278 |
+
|
| 279 |
+
// Populate Plans tab
|
| 280 |
+
// Clear and repopulate the plans table or list with selectedAgent.Plans
|
| 281 |
+
const planTable = document.getElementById('planTable');
|
| 282 |
+
planTable.innerHTML = '';
|
| 283 |
+
agents[selectedAgentIndex].Plans.forEach(plan => {
|
| 284 |
+
const newRow = `<tr>
|
| 285 |
+
<td>${plan.name}</td>
|
| 286 |
+
<td>${plan.createon}</td>
|
| 287 |
+
<td>${plan.tokencount}</td>
|
| 288 |
+
</tr>`;
|
| 289 |
+
planTable.insertAdjacentHTML('beforeend', newRow);
|
| 290 |
+
});
|
| 291 |
+
// Populate Documents tab
|
| 292 |
+
// Clear and repopulate the documents table with selectedAgent.Documents
|
| 293 |
+
const fileTable = document.getElementById('fileTable');
|
| 294 |
+
fileTable.innerHTML = '';
|
| 295 |
+
agents[selectedAgentIndex].Documents.forEach(doc => {
|
| 296 |
+
const newRow = `<tr>
|
| 297 |
+
<td><i class="bi bi-file-earmark-text file-icon"></i> ${doc.file}</td>
|
| 298 |
+
<td>${doc.createon}</td>
|
| 299 |
+
<td>${doc.size}</td>
|
| 300 |
+
<td>${doc.Access}</td>
|
| 301 |
+
<td><div class="progress"><div class="progress-bar"></div></div></td>
|
| 302 |
+
</tr>`;
|
| 303 |
+
fileTable.insertAdjacentHTML('beforeend', newRow);
|
| 304 |
+
});
|
| 305 |
+
// Display initial messages
|
| 306 |
+
//displayMessages();
|
| 307 |
+
}
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
function renderChatList() {
|
| 311 |
+
const chatList = document.getElementById('chatList');
|
| 312 |
+
chatList.innerHTML = ''; // Clear the existing list
|
| 313 |
+
|
| 314 |
+
agents.forEach((agent, index) => {
|
| 315 |
+
const newItem = document.createElement('li');
|
| 316 |
+
newItem.className = 'list-group-item';
|
| 317 |
+
newItem.innerHTML = `<div class="d-flex justify-content-between">
|
| 318 |
+
<span>${agent.Persona.agentname}</span>
|
| 319 |
+
<small>${new Date().toLocaleTimeString()}</small>
|
| 320 |
+
</div>`;
|
| 321 |
+
newItem.setAttribute('data-index', index);
|
| 322 |
+
newItem.setAttribute('data-messages', JSON.stringify(agent.Chat));
|
| 323 |
+
newItem.addEventListener('click', function() {
|
| 324 |
+
selectedAgentIndex = parseInt(this.getAttribute('data-index'));
|
| 325 |
+
displayMessages();
|
| 326 |
+
populateTabs();
|
| 327 |
+
});
|
| 328 |
+
newItem.addEventListener('contextmenu', function(e) {
|
| 329 |
+
e.preventDefault();
|
| 330 |
+
showContextMenu(e, newItem, index);
|
| 331 |
+
});
|
| 332 |
+
chatList.appendChild(newItem);
|
| 333 |
+
});
|
| 334 |
+
}
|
| 335 |
+
// Event listener for add chat button - Sidebar
|
| 336 |
+
document.getElementById('addChatBtn').addEventListener('click', function() {
|
| 337 |
+
var chatList = document.getElementById('chatList');
|
| 338 |
+
var newItem = document.createElement('li');
|
| 339 |
+
newItem.className = 'list-group-item';
|
| 340 |
+
newItem.innerHTML = `<div class="d-flex justify-content-between">
|
| 341 |
+
<span>New Agent</span>
|
| 342 |
+
<small>${new Date().toLocaleTimeString()}</small>
|
| 343 |
+
</div>`;
|
| 344 |
+
newItem.setAttribute('data-messages', JSON.stringify([]));
|
| 345 |
+
chatList.appendChild(newItem);
|
| 346 |
+
|
| 347 |
+
// Add new agent to agents array
|
| 348 |
+
var newAgent = {
|
| 349 |
+
"Persona": {
|
| 350 |
+
"agentname": `agent-${Date.now()}`,
|
| 351 |
+
"metaprompt": "you are a helpful assistant",
|
| 352 |
+
"prefill": "helps me with financial Reconciliation",
|
| 353 |
+
"tooluse": "true",
|
| 354 |
+
"filesearch": "false",
|
| 355 |
+
"codeinterpreter": "false"
|
| 356 |
+
},
|
| 357 |
+
"Plans": [],
|
| 358 |
+
"Documents": [],
|
| 359 |
+
"Chat": []
|
| 360 |
+
};
|
| 361 |
+
agents.push(newAgent);
|
| 362 |
+
renderChatList();
|
| 363 |
+
});
|
| 364 |
+
|
| 365 |
+
// Show context menu
|
| 366 |
+
function showContextMenu(event, listItem) {
|
| 367 |
+
var contextMenu = document.getElementById('contextMenu');
|
| 368 |
+
contextMenu.style.display = 'block';
|
| 369 |
+
contextMenu.style.left = event.pageX + 'px';
|
| 370 |
+
contextMenu.style.top = event.pageY + 'px';
|
| 371 |
+
|
| 372 |
+
document.getElementById('renameItem').onclick = function() {
|
| 373 |
+
var newName = prompt("Enter new name:", listItem.querySelector('span').textContent);
|
| 374 |
+
if (newName) {
|
| 375 |
+
listItem.querySelector('span').textContent = newName;
|
| 376 |
+
//write a code to update the agent name in agents array
|
| 377 |
+
agents[selectedAgentIndex].Persona.agentname = newName;
|
| 378 |
+
}
|
| 379 |
+
contextMenu.style.display = 'none';
|
| 380 |
+
};
|
| 381 |
+
|
| 382 |
+
document.addEventListener('click', function() {
|
| 383 |
+
contextMenu.style.display = 'none';
|
| 384 |
+
}, { once: true });
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
// Event listener for existing items
|
| 388 |
+
document.querySelectorAll('#chatList .list-group-item').forEach(item => {
|
| 389 |
+
item.addEventListener('contextmenu', function(e) {
|
| 390 |
+
e.preventDefault();
|
| 391 |
+
showContextMenu(e, item);
|
| 392 |
+
});
|
| 393 |
+
});
|
| 394 |
+
// Function to display messages
|
| 395 |
+
function displayMessages() {
|
| 396 |
+
const chatMessages = document.getElementById('chat-messages');
|
| 397 |
+
chatMessages.innerHTML = '';
|
| 398 |
+
agents[selectedAgentIndex].Chat.forEach(msg => {
|
| 399 |
+
const messageElement = document.createElement('div');
|
| 400 |
+
messageElement.classList.add('chat-message');
|
| 401 |
+
messageElement.innerHTML = `<strong>${msg.role}</strong><p>${msg.content}</p>`;
|
| 402 |
+
chatMessages.appendChild(messageElement);
|
| 403 |
+
});
|
| 404 |
+
}
|
| 405 |
+
|
| 406 |
+
// Event listener for sidebar items
|
| 407 |
+
document.querySelectorAll('#chatList .list-group-item').forEach(item => {
|
| 408 |
+
item.addEventListener('click', function() {
|
| 409 |
+
const newMessages = JSON.parse(this.getAttribute('data-messages'));
|
| 410 |
+
messages = [...newMessages];
|
| 411 |
+
displayMessages();
|
| 412 |
+
});
|
| 413 |
+
});
|
| 414 |
+
|
| 415 |
+
// Event listener for send button
|
| 416 |
+
document.getElementById('sendBtn').addEventListener('click', function() {
|
| 417 |
+
const input = document.getElementById('messageInput');
|
| 418 |
+
const userMessage = input.value;
|
| 419 |
+
if (userMessage) {
|
| 420 |
+
agents[selectedAgentIndex].Chat.push({ role: 'MB', content: userMessage });
|
| 421 |
+
if (userMessage.toLowerCase() === 'what is the capital of india') {
|
| 422 |
+
agents[0].Chat.push({ role: 'Copilot', content: 'New Delhi is the capital of India' });
|
| 423 |
+
}
|
| 424 |
+
displayMessages();
|
| 425 |
+
input.value = '';
|
| 426 |
+
}
|
| 427 |
+
});
|
| 428 |
+
|
| 429 |
+
// Event listener for upload button
|
| 430 |
+
document.getElementById('uploadBtn').addEventListener('click', function() {
|
| 431 |
+
document.getElementById('fileInput').click();
|
| 432 |
+
});
|
| 433 |
+
|
| 434 |
+
// Event listener for file input - Documents Tab
|
| 435 |
+
document.getElementById('fileInput').addEventListener('change', function(event) {
|
| 436 |
+
const file = event.target.files[0];
|
| 437 |
+
if (file) {
|
| 438 |
+
const newRow = `<tr>
|
| 439 |
+
<td><i class="bi bi-file-earmark-text file-icon"></i> ${file.name}</td>
|
| 440 |
+
<td>${new Date().toLocaleTimeString()}</td>
|
| 441 |
+
<td>${file.size}</td>
|
| 442 |
+
<td>This chat</td>
|
| 443 |
+
<td><div class="progress"><div class="progress-bar"></div></div></td>
|
| 444 |
+
</tr>`;
|
| 445 |
+
document.getElementById('fileTable').insertAdjacentHTML('beforeend', newRow);
|
| 446 |
+
}
|
| 447 |
+
});
|
| 448 |
+
|
| 449 |
+
// Event listener for save button - Personas Tab
|
| 450 |
+
document.getElementById('savePlanBtn').addEventListener('click', function() {
|
| 451 |
+
const agentname = document.getElementById('agentNameInput').value;
|
| 452 |
+
const metaprompt = document.getElementById('metaPromptInput').value;
|
| 453 |
+
const prefill = document.getElementById('prefillInput').value;
|
| 454 |
+
|
| 455 |
+
const plan = {
|
| 456 |
+
agentname,
|
| 457 |
+
metaprompt,
|
| 458 |
+
prefill
|
| 459 |
+
};
|
| 460 |
+
|
| 461 |
+
const savedPlansList = document.getElementById('savedPlansList');
|
| 462 |
+
const planItem = document.createElement('li');
|
| 463 |
+
planItem.classList.add('list-group-item');
|
| 464 |
+
planItem.textContent = `Agent Name: ${agentname}`;
|
| 465 |
+
planItem.addEventListener('click', function() {
|
| 466 |
+
alert(`Meta Prompt: ${plan.metaprompt}\nPrefill: ${plan.prefill}`);
|
| 467 |
+
});
|
| 468 |
+
|
| 469 |
+
savedPlansList.appendChild(planItem);
|
| 470 |
+
|
| 471 |
+
// Clear the inputs after saving
|
| 472 |
+
document.getElementById('agentNameInput').value = '';
|
| 473 |
+
document.getElementById('metaPromptInput').value = '';
|
| 474 |
+
document.getElementById('prefillInput').value = '';
|
| 475 |
+
});
|
| 476 |
+
|
| 477 |
+
|
| 478 |
+
|
| 479 |
+
// Initial rendering of the chat list
|
| 480 |
+
renderChatList();
|
| 481 |
+
|
| 482 |
+
// Populate tabs initially (if needed)
|
| 483 |
+
populateTabs();
|
| 484 |
+
"""))
|
| 485 |
+
return page
|
| 486 |
+
|
| 487 |
+
serve()
|
| 488 |
+
|
favicon.ico
ADDED
|
|
main.py
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
from fasthtml.common import *
|
| 3 |
+
from fasthtml_hf import setup_hf_backup
|
| 4 |
+
|
| 5 |
+
bootstraplink = Link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css", integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC", crossorigin="anonymous")
|
| 6 |
+
fontlink = Link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.8.1/font/bootstrap-icons.min.css")
|
| 7 |
+
favicon = Link(rel="icon", type="image/x-icon", href="https://raw.githubusercontent.com/rajeshradhakrishnanmvk/aitemplate/main/favicon.ico")
|
| 8 |
+
|
| 9 |
+
title = Title("Groqlet Expendables")
|
| 10 |
+
css = Style("""body {
|
| 11 |
+
display: flex;
|
| 12 |
+
height: 100vh;
|
| 13 |
+
overflow: hidden;
|
| 14 |
+
}
|
| 15 |
+
#sidebar {
|
| 16 |
+
background-color: #f8f9fa;
|
| 17 |
+
padding: 10px;
|
| 18 |
+
overflow-y: auto;
|
| 19 |
+
height: 100vh;
|
| 20 |
+
}
|
| 21 |
+
#chat {
|
| 22 |
+
display: flex;
|
| 23 |
+
flex-direction: column;
|
| 24 |
+
height: 100vh;
|
| 25 |
+
overflow-y: hidden;
|
| 26 |
+
}
|
| 27 |
+
#chat-messages {
|
| 28 |
+
flex-grow: 1;
|
| 29 |
+
overflow-y: auto;
|
| 30 |
+
padding: 10px;
|
| 31 |
+
}
|
| 32 |
+
#chat-input {
|
| 33 |
+
padding: 10px;
|
| 34 |
+
border-top: 1px solid #e9ecef;
|
| 35 |
+
}
|
| 36 |
+
#documentsTab {
|
| 37 |
+
padding: 20px;
|
| 38 |
+
}
|
| 39 |
+
.file-upload {
|
| 40 |
+
display: none;
|
| 41 |
+
}
|
| 42 |
+
.file-icon {
|
| 43 |
+
width: 20px;
|
| 44 |
+
height: 20px;
|
| 45 |
+
}
|
| 46 |
+
.progress-bar {
|
| 47 |
+
width: 100%;
|
| 48 |
+
height: 100%;
|
| 49 |
+
background-color: #4caf50;
|
| 50 |
+
}
|
| 51 |
+
.container-fluid {
|
| 52 |
+
overflow-y: auto;
|
| 53 |
+
}
|
| 54 |
+
.form-label {
|
| 55 |
+
font-weight: bold;
|
| 56 |
+
}
|
| 57 |
+
.list-group-item {
|
| 58 |
+
cursor: pointer;
|
| 59 |
+
}""")
|
| 60 |
+
|
| 61 |
+
app = FastHTML(hdrs=(title,favicon,bootstraplink, fontlink,css))
|
| 62 |
+
|
| 63 |
+
data = json.dumps([
|
| 64 |
+
{
|
| 65 |
+
"Persona": {
|
| 66 |
+
"agentname": "dinkan-1",
|
| 67 |
+
"metaprompt": "you are a helpful assistant",
|
| 68 |
+
"prefill": "helps me with financial Reconciliation",
|
| 69 |
+
"tooluse": "true",
|
| 70 |
+
"filesearch": "true",
|
| 71 |
+
"codeinterpreter": "true"
|
| 72 |
+
},
|
| 73 |
+
"Plans": [
|
| 74 |
+
{ "name": "askquestion", "createon": "06/8/2024", "tokencount": "2048" }
|
| 75 |
+
],
|
| 76 |
+
"Documents": [
|
| 77 |
+
{ "file": "./reconciliation.txt", "createon": "06/8/2024", "size": "30,079", "Access": "private", "progress": "success" },
|
| 78 |
+
{ "file": "./design.pdf", "createon": "07/8/2024", "size": "30,079", "Access": "public", "progress": "error" }
|
| 79 |
+
],
|
| 80 |
+
"Chat": [
|
| 81 |
+
{"role": "system", "content":"Hello, thank you for democratizing AI's productivity benefits with open source! How can I help you today?"},
|
| 82 |
+
{ "role": "assistant", "content": "what is the capital of India" },
|
| 83 |
+
{ "role": "user", "content": "New Delhi is the capital of India" }
|
| 84 |
+
]
|
| 85 |
+
},
|
| 86 |
+
{
|
| 87 |
+
"Persona": {
|
| 88 |
+
"agentname": "dinkan-2",
|
| 89 |
+
"metaprompt": "you are a helpful assistant",
|
| 90 |
+
"prefill": "helps me with financial Reconciliation",
|
| 91 |
+
"tooluse": "true",
|
| 92 |
+
"filesearch": "false",
|
| 93 |
+
"codeinterpreter": "false"
|
| 94 |
+
},
|
| 95 |
+
"Plans": [
|
| 96 |
+
{ "name": "calculate", "createon": "07/8/2024", "tokencount": "1024" }
|
| 97 |
+
],
|
| 98 |
+
"Documents": [
|
| 99 |
+
{ "file": "./design.txt", "createon": "08/8/2024", "size": "30,079", "Access": "private", "progress": "success" },
|
| 100 |
+
{ "file": "./design.pdf", "createon": "09/8/2024", "size": "30,079", "Access": "public", "progress": "error" }
|
| 101 |
+
],
|
| 102 |
+
"Chat": [
|
| 103 |
+
{"role": "system", "content":"Hello, thank you for democratizing AI's productivity benefits with open source! How can I help you today?"},
|
| 104 |
+
{ "role": "assistant", "content": "what is the capital of Kerala" },
|
| 105 |
+
{ "role": "user", "content": "Trivandrum is the capital of India" }
|
| 106 |
+
]
|
| 107 |
+
}
|
| 108 |
+
])
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
@app.route("/")
|
| 112 |
+
def get():
|
| 113 |
+
page = (Div(
|
| 114 |
+
Nav(
|
| 115 |
+
Div(
|
| 116 |
+
A("Groqlet Expendables", cls="navbar-brand", href="#"),
|
| 117 |
+
Div(
|
| 118 |
+
A(
|
| 119 |
+
I(cls="bi bi-plug"),
|
| 120 |
+
"Plugins", cls="nav-link text-white", href="#", style="margin-right: 10px;"),
|
| 121 |
+
A(
|
| 122 |
+
I(cls="bi bi-gear"),
|
| 123 |
+
"Settings", cls="nav-link text-white", href="#", style="margin-right: 10px;"),
|
| 124 |
+
|
| 125 |
+
Img(cls="rounded-circle", src="https://media.licdn.com/dms/image/C4D03AQHwjVMduekRjw/profile-displayphoto-shrink_100_100/0/1516794061157?e=1728518400&v=beta&t=JwjApmMV83LH01mtr8jUhh5wayHWFqPEhneLEU10HRI", alt="User Icon", style="width: 30px; height: 30px;")
|
| 126 |
+
,cls="d-flex align-items-center")
|
| 127 |
+
,cls="container-fluid")
|
| 128 |
+
,cls="navbar navbar-expand-lg navbar-dark",style="background-color: #800080;"),
|
| 129 |
+
Div(
|
| 130 |
+
Div(
|
| 131 |
+
Div(
|
| 132 |
+
H4("Agents"),
|
| 133 |
+
Button("+", cls="btn btn-primary btn-sm", id="addChatBtn")
|
| 134 |
+
, cls="d-flex justify-content-between align-items-center mb-2"),
|
| 135 |
+
Ul(
|
| 136 |
+
Li(
|
| 137 |
+
Div(
|
| 138 |
+
Span("Can you tell me a story?"),
|
| 139 |
+
Small("11:10 PM")
|
| 140 |
+
, cls="d-flex justify-content-between")
|
| 141 |
+
, cls="list-group-item")
|
| 142 |
+
, cls="list-group", id="chatList")
|
| 143 |
+
, cls="col-12 col-md-3", id="sidebar"),
|
| 144 |
+
Div(
|
| 145 |
+
A("Rename", cls="dropdown-item", href="#", id="renameItem")
|
| 146 |
+
,id="contextMenu", cls="dropdown-menu", style="display:none; position:absolute;"),
|
| 147 |
+
Div(
|
| 148 |
+
Ul(
|
| 149 |
+
Li(
|
| 150 |
+
A("Chat", cls="nav-link active", data_bs_toggle="tab", href="#chatTab")
|
| 151 |
+
, cls="nav-item"),
|
| 152 |
+
Li(
|
| 153 |
+
A("Documents", cls="nav-link", data_bs_toggle="tab", href="#documentsTab")
|
| 154 |
+
, cls="nav-item"),
|
| 155 |
+
Li(
|
| 156 |
+
A("Plans", cls="nav-link", data_bs_toggle="tab", href="#plansTab")
|
| 157 |
+
, cls="nav-item"),
|
| 158 |
+
Li(
|
| 159 |
+
A("Personas", cls="nav-link", data_bs_toggle="tab", href="#personasTab")
|
| 160 |
+
, cls="nav-item")
|
| 161 |
+
, cls="nav nav-tabs"),
|
| 162 |
+
Div(
|
| 163 |
+
Div(
|
| 164 |
+
Div(
|
| 165 |
+
Div(
|
| 166 |
+
Strong("Copilot"),
|
| 167 |
+
P("Hello, thank you for democratizing AI's productivity benefits with open source! How can I help you today?")
|
| 168 |
+
, cls="chat-message"),
|
| 169 |
+
Div(
|
| 170 |
+
Strong("MB"),
|
| 171 |
+
P("Can you tell me a story about a prince in a paragraph?")
|
| 172 |
+
, cls="chat-message")
|
| 173 |
+
, id="chat-messages"),
|
| 174 |
+
Div(
|
| 175 |
+
Input(type="text", cls="form-control me-2", placeholder="Type a message...", id="messageInput"),
|
| 176 |
+
Button("Send", cls="btn btn-primary", id="sendBtn")
|
| 177 |
+
, id="chat-input", cls="d-flex")
|
| 178 |
+
, cls="tab-pane fade show active", id="chatTab"),
|
| 179 |
+
Div(
|
| 180 |
+
Div(
|
| 181 |
+
H4("Documents"),
|
| 182 |
+
Button("Upload", cls="btn btn-primary btn-sm", id="uploadBtn"),
|
| 183 |
+
Input(type="file", id="fileInput", cls="file-upload")
|
| 184 |
+
, cls="d-flex justify-content-between align-items-center mb-2"),
|
| 185 |
+
Div(
|
| 186 |
+
Div(
|
| 187 |
+
Input(cls="form-check-input", type="radio", name="vectorDatabase", id="volatile", value="volatile"),
|
| 188 |
+
Label("Volatile", cls="form-check-label", _for="volatile")
|
| 189 |
+
, cls="form-check me-3"),
|
| 190 |
+
Div(
|
| 191 |
+
Input(cls="form-check-input", type="radio", name="vectorDatabase", id="textFile", value="textFile", checked=1),
|
| 192 |
+
Label("TextFile", cls="form-check-label", _for="textFile")
|
| 193 |
+
, cls="form-check me-3"),
|
| 194 |
+
Div(
|
| 195 |
+
Input(cls="form-check-input", type="radio", name="vectorDatabase", id="qdrant", value="qdrant"),
|
| 196 |
+
Label( "Qdrant", cls="form-check-label", _for="qdrant")
|
| 197 |
+
, cls="form-check me-3"),
|
| 198 |
+
Div(
|
| 199 |
+
Input(cls="form-check-input", type="radio", name="vectorDatabase", id="llamaindexSearch", value="llamaindexSearch"),
|
| 200 |
+
Label("llamaindex Search", cls="form-check-label", _for="llamaindexSearch")
|
| 201 |
+
, cls="form-check me-3")
|
| 202 |
+
,cls="d-flex mb-2"),
|
| 203 |
+
Table(
|
| 204 |
+
Thead(),
|
| 205 |
+
Tr(
|
| 206 |
+
Th("Name"),
|
| 207 |
+
Th("Created on"),
|
| 208 |
+
Th("Size (bytes)"),
|
| 209 |
+
Th("Access"),
|
| 210 |
+
Th("Progress")),
|
| 211 |
+
Tbody(
|
| 212 |
+
Tr(
|
| 213 |
+
Td(I(cls="bi bi-file-earmark-text file-icon"), " reconciliation.txt"),
|
| 214 |
+
Td("9:38 am"),
|
| 215 |
+
Td("30,079"),
|
| 216 |
+
Td("This chat"),
|
| 217 |
+
Td(Div(cls="progress"),Div(cls="progress-bar"))),id="fileTable"),cls="table")
|
| 218 |
+
,cls="tab-pane fade", id="documentsTab"),
|
| 219 |
+
Div(
|
| 220 |
+
Table(
|
| 221 |
+
Thead(),
|
| 222 |
+
Tr(
|
| 223 |
+
Th("Goal"),
|
| 224 |
+
Th("Created on"),
|
| 225 |
+
Th("Token Count")),
|
| 226 |
+
Tbody(id="planTable"),
|
| 227 |
+
Tr(
|
| 228 |
+
Td("askQuestions"),
|
| 229 |
+
Td("9:38 am"),
|
| 230 |
+
Td("30,079")),cls="table")
|
| 231 |
+
, cls="tab-pane fade", id="plansTab"),
|
| 232 |
+
Div(
|
| 233 |
+
Div(
|
| 234 |
+
H4("Persona"),
|
| 235 |
+
Div(
|
| 236 |
+
Label("Agent Name", cls="form-label", _for="agentNameInput"),
|
| 237 |
+
Input(type="text", cls="form-control", id="agentNameInput", placeholder="Enter your agent's name...")
|
| 238 |
+
, cls="mb-3"),
|
| 239 |
+
Div(
|
| 240 |
+
Label("Meta Prompt", cls="form-label", _for="metaPromptInput"),
|
| 241 |
+
Textarea(cls="form-control", id="metaPromptInput", rows="3", placeholder="Enter your Meta Prompt...")
|
| 242 |
+
, cls="mb-3"),
|
| 243 |
+
Div(
|
| 244 |
+
Label("Prefill", cls="form-label", _for="prefillInput"),
|
| 245 |
+
Textarea(cls="form-control", id="prefillInput", rows="3", placeholder="Enter agent's prefill...")
|
| 246 |
+
, cls="mb-3"),
|
| 247 |
+
Div(
|
| 248 |
+
Button("Save", cls="btn btn-primary", id="savePlanBtn")
|
| 249 |
+
, cls="d-flex justify-content-end"),
|
| 250 |
+
Hr(),
|
| 251 |
+
H5("Saved Plans"),
|
| 252 |
+
Ul(cls="list-group", id="savedPlansList")
|
| 253 |
+
, cls="container-fluid p-3")
|
| 254 |
+
, cls="tab-pane fade", id="personasTab")
|
| 255 |
+
|
| 256 |
+
, cls="tab-content flex-grow-1")
|
| 257 |
+
, cls="col-12 col-md-9 d-flex flex-column", id="chat")
|
| 258 |
+
, cls="row")
|
| 259 |
+
,cls="container-fluid"),
|
| 260 |
+
|
| 261 |
+
Script(src="https://code.jquery.com/jquery-3.6.0.min.js"),
|
| 262 |
+
Script(src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js", integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p",crossorigin="anonymous"),
|
| 263 |
+
Script(f"let agents = {data};"),
|
| 264 |
+
Script("""
|
| 265 |
+
let selectedAgentIndex = -1;
|
| 266 |
+
|
| 267 |
+
function populateTabs() {
|
| 268 |
+
if (selectedAgentIndex >= 0) {
|
| 269 |
+
const selectedAgent = agents[selectedAgentIndex];
|
| 270 |
+
|
| 271 |
+
// Populate Personas tab
|
| 272 |
+
const agentNameInput = document.getElementById('agentNameInput');
|
| 273 |
+
const metaPromptInput = document.getElementById('metaPromptInput');
|
| 274 |
+
const prefillInput = document.getElementById('prefillInput');
|
| 275 |
+
|
| 276 |
+
agentNameInput.value = agents[selectedAgentIndex].Persona.agentname;
|
| 277 |
+
metaPromptInput.value = agents[selectedAgentIndex].Persona.metaprompt;
|
| 278 |
+
prefillInput.value = agents[selectedAgentIndex].Persona.prefill;
|
| 279 |
+
|
| 280 |
+
// Populate Plans tab
|
| 281 |
+
// Clear and repopulate the plans table or list with selectedAgent.Plans
|
| 282 |
+
const planTable = document.getElementById('planTable');
|
| 283 |
+
planTable.innerHTML = '';
|
| 284 |
+
agents[selectedAgentIndex].Plans.forEach(plan => {
|
| 285 |
+
const newRow = `<tr>
|
| 286 |
+
<td>${plan.name}</td>
|
| 287 |
+
<td>${plan.createon}</td>
|
| 288 |
+
<td>${plan.tokencount}</td>
|
| 289 |
+
</tr>`;
|
| 290 |
+
planTable.insertAdjacentHTML('beforeend', newRow);
|
| 291 |
+
});
|
| 292 |
+
// Populate Documents tab
|
| 293 |
+
// Clear and repopulate the documents table with selectedAgent.Documents
|
| 294 |
+
const fileTable = document.getElementById('fileTable');
|
| 295 |
+
fileTable.innerHTML = '';
|
| 296 |
+
agents[selectedAgentIndex].Documents.forEach(doc => {
|
| 297 |
+
const newRow = `<tr>
|
| 298 |
+
<td><i class="bi bi-file-earmark-text file-icon"></i> ${doc.file}</td>
|
| 299 |
+
<td>${doc.createon}</td>
|
| 300 |
+
<td>${doc.size}</td>
|
| 301 |
+
<td>${doc.Access}</td>
|
| 302 |
+
<td><div class="progress"><div class="progress-bar"></div></div></td>
|
| 303 |
+
</tr>`;
|
| 304 |
+
fileTable.insertAdjacentHTML('beforeend', newRow);
|
| 305 |
+
});
|
| 306 |
+
// Display initial messages
|
| 307 |
+
//displayMessages();
|
| 308 |
+
}
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
function renderChatList() {
|
| 312 |
+
const chatList = document.getElementById('chatList');
|
| 313 |
+
chatList.innerHTML = ''; // Clear the existing list
|
| 314 |
+
|
| 315 |
+
agents.forEach((agent, index) => {
|
| 316 |
+
const newItem = document.createElement('li');
|
| 317 |
+
newItem.className = 'list-group-item';
|
| 318 |
+
newItem.innerHTML = `<div class="d-flex justify-content-between">
|
| 319 |
+
<span>${agent.Persona.agentname}</span>
|
| 320 |
+
<small>${new Date().toLocaleTimeString()}</small>
|
| 321 |
+
</div>`;
|
| 322 |
+
newItem.setAttribute('data-index', index);
|
| 323 |
+
newItem.setAttribute('data-messages', JSON.stringify(agent.Chat));
|
| 324 |
+
newItem.addEventListener('click', function() {
|
| 325 |
+
selectedAgentIndex = parseInt(this.getAttribute('data-index'));
|
| 326 |
+
displayMessages();
|
| 327 |
+
populateTabs();
|
| 328 |
+
});
|
| 329 |
+
newItem.addEventListener('contextmenu', function(e) {
|
| 330 |
+
e.preventDefault();
|
| 331 |
+
showContextMenu(e, newItem, index);
|
| 332 |
+
});
|
| 333 |
+
chatList.appendChild(newItem);
|
| 334 |
+
});
|
| 335 |
+
}
|
| 336 |
+
// Event listener for add chat button - Sidebar
|
| 337 |
+
document.getElementById('addChatBtn').addEventListener('click', function() {
|
| 338 |
+
var chatList = document.getElementById('chatList');
|
| 339 |
+
var newItem = document.createElement('li');
|
| 340 |
+
newItem.className = 'list-group-item';
|
| 341 |
+
newItem.innerHTML = `<div class="d-flex justify-content-between">
|
| 342 |
+
<span>New Agent</span>
|
| 343 |
+
<small>${new Date().toLocaleTimeString()}</small>
|
| 344 |
+
</div>`;
|
| 345 |
+
newItem.setAttribute('data-messages', JSON.stringify([]));
|
| 346 |
+
chatList.appendChild(newItem);
|
| 347 |
+
|
| 348 |
+
// Add new agent to agents array
|
| 349 |
+
var newAgent = {
|
| 350 |
+
"Persona": {
|
| 351 |
+
"agentname": `agent-${Date.now()}`,
|
| 352 |
+
"metaprompt": "you are a helpful assistant",
|
| 353 |
+
"prefill": "helps me with financial Reconciliation",
|
| 354 |
+
"tooluse": "true",
|
| 355 |
+
"filesearch": "false",
|
| 356 |
+
"codeinterpreter": "false"
|
| 357 |
+
},
|
| 358 |
+
"Plans": [],
|
| 359 |
+
"Documents": [],
|
| 360 |
+
"Chat": []
|
| 361 |
+
};
|
| 362 |
+
agents.push(newAgent);
|
| 363 |
+
renderChatList();
|
| 364 |
+
});
|
| 365 |
+
|
| 366 |
+
// Show context menu
|
| 367 |
+
function showContextMenu(event, listItem) {
|
| 368 |
+
var contextMenu = document.getElementById('contextMenu');
|
| 369 |
+
contextMenu.style.display = 'block';
|
| 370 |
+
contextMenu.style.left = event.pageX + 'px';
|
| 371 |
+
contextMenu.style.top = event.pageY + 'px';
|
| 372 |
+
|
| 373 |
+
document.getElementById('renameItem').onclick = function() {
|
| 374 |
+
var newName = prompt("Enter new name:", listItem.querySelector('span').textContent);
|
| 375 |
+
if (newName) {
|
| 376 |
+
listItem.querySelector('span').textContent = newName;
|
| 377 |
+
//write a code to update the agent name in agents array
|
| 378 |
+
agents[selectedAgentIndex].Persona.agentname = newName;
|
| 379 |
+
}
|
| 380 |
+
contextMenu.style.display = 'none';
|
| 381 |
+
};
|
| 382 |
+
|
| 383 |
+
document.addEventListener('click', function() {
|
| 384 |
+
contextMenu.style.display = 'none';
|
| 385 |
+
}, { once: true });
|
| 386 |
+
}
|
| 387 |
+
|
| 388 |
+
// Event listener for existing items
|
| 389 |
+
document.querySelectorAll('#chatList .list-group-item').forEach(item => {
|
| 390 |
+
item.addEventListener('contextmenu', function(e) {
|
| 391 |
+
e.preventDefault();
|
| 392 |
+
showContextMenu(e, item);
|
| 393 |
+
});
|
| 394 |
+
});
|
| 395 |
+
// Function to display messages
|
| 396 |
+
function displayMessages() {
|
| 397 |
+
const chatMessages = document.getElementById('chat-messages');
|
| 398 |
+
chatMessages.innerHTML = '';
|
| 399 |
+
agents[selectedAgentIndex].Chat.forEach(msg => {
|
| 400 |
+
const messageElement = document.createElement('div');
|
| 401 |
+
messageElement.classList.add('chat-message');
|
| 402 |
+
messageElement.innerHTML = `<strong>${msg.role}</strong><p>${msg.content}</p>`;
|
| 403 |
+
chatMessages.appendChild(messageElement);
|
| 404 |
+
});
|
| 405 |
+
}
|
| 406 |
+
|
| 407 |
+
// Event listener for sidebar items
|
| 408 |
+
document.querySelectorAll('#chatList .list-group-item').forEach(item => {
|
| 409 |
+
item.addEventListener('click', function() {
|
| 410 |
+
const newMessages = JSON.parse(this.getAttribute('data-messages'));
|
| 411 |
+
messages = [...newMessages];
|
| 412 |
+
displayMessages();
|
| 413 |
+
});
|
| 414 |
+
});
|
| 415 |
+
|
| 416 |
+
// Event listener for send button
|
| 417 |
+
document.getElementById('sendBtn').addEventListener('click', function() {
|
| 418 |
+
const input = document.getElementById('messageInput');
|
| 419 |
+
const userMessage = input.value;
|
| 420 |
+
if (userMessage) {
|
| 421 |
+
agents[selectedAgentIndex].Chat.push({ role: 'MB', content: userMessage });
|
| 422 |
+
if (userMessage.toLowerCase() === 'what is the capital of india') {
|
| 423 |
+
agents[0].Chat.push({ role: 'Copilot', content: 'New Delhi is the capital of India' });
|
| 424 |
+
}
|
| 425 |
+
displayMessages();
|
| 426 |
+
input.value = '';
|
| 427 |
+
}
|
| 428 |
+
});
|
| 429 |
+
|
| 430 |
+
// Event listener for upload button
|
| 431 |
+
document.getElementById('uploadBtn').addEventListener('click', function() {
|
| 432 |
+
document.getElementById('fileInput').click();
|
| 433 |
+
});
|
| 434 |
+
|
| 435 |
+
// Event listener for file input - Documents Tab
|
| 436 |
+
document.getElementById('fileInput').addEventListener('change', function(event) {
|
| 437 |
+
const file = event.target.files[0];
|
| 438 |
+
if (file) {
|
| 439 |
+
const newRow = `<tr>
|
| 440 |
+
<td><i class="bi bi-file-earmark-text file-icon"></i> ${file.name}</td>
|
| 441 |
+
<td>${new Date().toLocaleTimeString()}</td>
|
| 442 |
+
<td>${file.size}</td>
|
| 443 |
+
<td>This chat</td>
|
| 444 |
+
<td><div class="progress"><div class="progress-bar"></div></div></td>
|
| 445 |
+
</tr>`;
|
| 446 |
+
document.getElementById('fileTable').insertAdjacentHTML('beforeend', newRow);
|
| 447 |
+
}
|
| 448 |
+
});
|
| 449 |
+
|
| 450 |
+
// Event listener for save button - Personas Tab
|
| 451 |
+
document.getElementById('savePlanBtn').addEventListener('click', function() {
|
| 452 |
+
const agentname = document.getElementById('agentNameInput').value;
|
| 453 |
+
const metaprompt = document.getElementById('metaPromptInput').value;
|
| 454 |
+
const prefill = document.getElementById('prefillInput').value;
|
| 455 |
+
|
| 456 |
+
const plan = {
|
| 457 |
+
agentname,
|
| 458 |
+
metaprompt,
|
| 459 |
+
prefill
|
| 460 |
+
};
|
| 461 |
+
|
| 462 |
+
const savedPlansList = document.getElementById('savedPlansList');
|
| 463 |
+
const planItem = document.createElement('li');
|
| 464 |
+
planItem.classList.add('list-group-item');
|
| 465 |
+
planItem.textContent = `Agent Name: ${agentname}`;
|
| 466 |
+
planItem.addEventListener('click', function() {
|
| 467 |
+
alert(`Meta Prompt: ${plan.metaprompt}\nPrefill: ${plan.prefill}`);
|
| 468 |
+
});
|
| 469 |
+
|
| 470 |
+
savedPlansList.appendChild(planItem);
|
| 471 |
+
|
| 472 |
+
// Clear the inputs after saving
|
| 473 |
+
document.getElementById('agentNameInput').value = '';
|
| 474 |
+
document.getElementById('metaPromptInput').value = '';
|
| 475 |
+
document.getElementById('prefillInput').value = '';
|
| 476 |
+
});
|
| 477 |
+
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
// Initial rendering of the chat list
|
| 481 |
+
renderChatList();
|
| 482 |
+
|
| 483 |
+
// Populate tabs initially (if needed)
|
| 484 |
+
populateTabs();
|
| 485 |
+
"""))
|
| 486 |
+
return page
|
| 487 |
+
setup_hf_backup(app)
|
| 488 |
+
serve()
|
| 489 |
+
|
polling.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dotenv import load_dotenv, find_dotenv
|
| 2 |
+
from fasthtml.common import *
|
| 3 |
+
from groq import Groq
|
| 4 |
+
|
| 5 |
+
# Set up the app, including daisyui and tailwind for the chat component
|
| 6 |
+
tlink = Script(src="https://cdn.tailwindcss.com"),
|
| 7 |
+
dlink = Link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/daisyui@4.11.1/dist/full.min.css")
|
| 8 |
+
app = FastHTML(hdrs=(tlink, dlink, picolink))
|
| 9 |
+
|
| 10 |
+
load_dotenv(find_dotenv()) #os.environ["GROQ_API_KEY"]
|
| 11 |
+
client = Groq()
|
| 12 |
+
sp = """You are a helpful and concise assistant."""
|
| 13 |
+
messages = []
|
| 14 |
+
|
| 15 |
+
# Chat message component, polling if message is still being generated
|
| 16 |
+
def ChatMessage(msg_idx):
|
| 17 |
+
msg = messages[msg_idx]
|
| 18 |
+
text = "..." if msg['content'] == "" else msg['content']
|
| 19 |
+
bubble_class = f"chat-bubble-{'primary' if msg['role'] == 'user' else 'secondary'}"
|
| 20 |
+
chat_class = f"chat-{'end' if msg['role'] == 'user' else 'start'}"
|
| 21 |
+
generating = 'generating' in messages[msg_idx] and messages[msg_idx]['generating']
|
| 22 |
+
print(generating)
|
| 23 |
+
stream_args = {"hx_trigger":"every 0.1s", "hx_swap":"outerHTML", "hx_get":f"/chat_message/{msg_idx}"}
|
| 24 |
+
return Div(Div(msg['role'], cls="chat-header"),
|
| 25 |
+
Div(text, cls=f"chat-bubble {bubble_class}"),
|
| 26 |
+
cls=f"chat {chat_class}", id=f"chat-message-{msg_idx}",
|
| 27 |
+
**stream_args if generating else {})
|
| 28 |
+
|
| 29 |
+
# Route that gets polled while streaming
|
| 30 |
+
@app.get("/chat_message/{msg_idx}")
|
| 31 |
+
def get_chat_message(msg_idx:int):
|
| 32 |
+
if msg_idx >= len(messages): return ""
|
| 33 |
+
return ChatMessage(msg_idx)
|
| 34 |
+
|
| 35 |
+
# The input field for the user message. Also used to clear the
|
| 36 |
+
# input field after sending a message via an OOB swap
|
| 37 |
+
def ChatInput():
|
| 38 |
+
return Input(type="text", name='msg', id='msg-input',
|
| 39 |
+
placeholder="Type a message",
|
| 40 |
+
cls="input input-bordered w-full", hx_swap_oob='true')
|
| 41 |
+
|
| 42 |
+
# The main screen
|
| 43 |
+
@app.route("/")
|
| 44 |
+
def get():
|
| 45 |
+
page = Body(H1('Agentic Bot 1002'),
|
| 46 |
+
Div(*[ChatMessage(msg) for msg in messages],
|
| 47 |
+
id="chatlist", cls="chat-box h-[73vh] overflow-y-auto"),
|
| 48 |
+
Form(Group(ChatInput(), Button("Send", cls="btn btn-primary")),
|
| 49 |
+
hx_post="/", hx_target="#chatlist", hx_swap="beforeend",
|
| 50 |
+
cls="flex space-x-2 mt-2",
|
| 51 |
+
), cls="p-4 max-w-lg mx-auto")
|
| 52 |
+
return Title('Agentic Bot 1002'), page
|
| 53 |
+
|
| 54 |
+
# Run the chat model in a separate thread
|
| 55 |
+
@threaded
|
| 56 |
+
def get_response(r, idx): #.choices[0].delta.content
|
| 57 |
+
for chunk in r:
|
| 58 |
+
if chunk.choices[0].delta.content is not None:
|
| 59 |
+
messages[idx]["content"] += chunk.choices[0].delta.content
|
| 60 |
+
messages[idx]["generating"] = False
|
| 61 |
+
|
| 62 |
+
# Handle the form submission
|
| 63 |
+
@app.post("/")
|
| 64 |
+
def post(msg:str):
|
| 65 |
+
messages.append({"role":"system", "content":sp})
|
| 66 |
+
idx = len(messages)
|
| 67 |
+
messages.append({"role":"user", "content":msg})
|
| 68 |
+
# r = cli(messages, sp=sp, stream=True) # Send message to chat model (with streaming)
|
| 69 |
+
# Remove 'generating' key-value pair if it exists
|
| 70 |
+
for entry in messages:
|
| 71 |
+
if 'generating' in entry:
|
| 72 |
+
del entry['generating']
|
| 73 |
+
stream = client.chat.completions.create(
|
| 74 |
+
messages=messages,
|
| 75 |
+
model="llama3-8b-8192",
|
| 76 |
+
temperature=0.5,
|
| 77 |
+
max_tokens=1024,
|
| 78 |
+
top_p=1,
|
| 79 |
+
stop=None,
|
| 80 |
+
stream=True,
|
| 81 |
+
)
|
| 82 |
+
messages.append({"role":"assistant", "generating":True, "content":""}) # Response initially blank
|
| 83 |
+
get_response(stream, idx+1) # Start a new thread to fill in content
|
| 84 |
+
return (ChatMessage(idx), # The user's message
|
| 85 |
+
ChatMessage(idx+1), # The chatbot's response
|
| 86 |
+
ChatInput()) # And clear the input field via an OOB swap
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
if __name__ == '__main__': uvicorn.run("polling:app", host='0.0.0.0', port=8000, reload=True)
|
requirements.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
python-fasthtml
|
| 2 |
+
fasthtml-hf
|
| 3 |
+
uvicorn>=0.29
|
| 4 |
+
groq
|
| 5 |
+
python-dotenv
|
simple.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fasthtml.common import *
|
| 2 |
+
from groq import Groq
|
| 3 |
+
from dotenv import load_dotenv, find_dotenv
|
| 4 |
+
|
| 5 |
+
# Set up the app, including daisyui and tailwind for the chat component
|
| 6 |
+
tlink = Script(src="https://cdn.tailwindcss.com"),
|
| 7 |
+
dlink = Link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/daisyui@4.11.1/dist/full.min.css")
|
| 8 |
+
app = FastHTML(hdrs=(tlink, dlink, picolink))
|
| 9 |
+
|
| 10 |
+
load_dotenv(find_dotenv()) #os.environ["GROQ_API_KEY"]
|
| 11 |
+
client = Groq()
|
| 12 |
+
sp = """You are a helpful and concise assistant."""
|
| 13 |
+
messages = []
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
# Chat message component (renders a chat bubble)
|
| 17 |
+
def ChatMessage(msg):
|
| 18 |
+
bubble_class = f"chat-bubble-{'primary' if msg['role'] == 'user' else 'secondary'}"
|
| 19 |
+
chat_class = f"chat-{'end' if msg['role'] == 'user' else 'start'}"
|
| 20 |
+
return Div(Div(msg['role'], cls="chat-header"),
|
| 21 |
+
Div(msg['content'], cls=f"chat-bubble {bubble_class}"),
|
| 22 |
+
cls=f"chat {chat_class}")
|
| 23 |
+
|
| 24 |
+
# The input field for the user message. Also used to clear the
|
| 25 |
+
# input field after sending a message via an OOB swap
|
| 26 |
+
def ChatInput():
|
| 27 |
+
return Input(type="text", name='msg', id='msg-input',
|
| 28 |
+
placeholder="Type a message",
|
| 29 |
+
cls="input input-bordered w-full", hx_swap_oob='true')
|
| 30 |
+
|
| 31 |
+
# The main screen
|
| 32 |
+
@app.route("/")
|
| 33 |
+
def get():
|
| 34 |
+
page = Body(H1('Agentic Bot 1001'),
|
| 35 |
+
Div(*[ChatMessage(msg) for msg in messages],
|
| 36 |
+
id="chatlist", cls="chat-box h-[73vh] overflow-y-auto"),
|
| 37 |
+
Form(Group(ChatInput(), Button("Send", cls="btn btn-primary")),
|
| 38 |
+
hx_post="/", hx_target="#chatlist", hx_swap="beforeend",
|
| 39 |
+
cls="flex space-x-2 mt-2",
|
| 40 |
+
), cls="p-4 max-w-lg mx-auto")
|
| 41 |
+
return Title('Agentic Bot 1001'), page
|
| 42 |
+
|
| 43 |
+
# Handle the form submission
|
| 44 |
+
@app.post("/")
|
| 45 |
+
def post(msg:str):
|
| 46 |
+
messages.append({"role":"system", "content":sp})
|
| 47 |
+
messages.append({"role":"user", "content":msg})
|
| 48 |
+
#r = cli(messages, sp=sp) # get response from chat model
|
| 49 |
+
chat_completion = client.chat.completions.create(
|
| 50 |
+
messages=messages,
|
| 51 |
+
model="llama3-8b-8192",
|
| 52 |
+
temperature=0.5,
|
| 53 |
+
max_tokens=1024,
|
| 54 |
+
top_p=1,
|
| 55 |
+
stop=None,
|
| 56 |
+
stream=False,
|
| 57 |
+
)
|
| 58 |
+
messages.append({"role":"assistant", "content":chat_completion.choices[0].message.content})
|
| 59 |
+
return (ChatMessage(messages[-2]), # The user's message
|
| 60 |
+
ChatMessage(messages[-1]), # The chatbot's response
|
| 61 |
+
ChatInput()) # And clear the input field via an OOB swap
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
if __name__ == '__main__': uvicorn.run("simple:app", host='0.0.0.0', port=8000, reload=True)
|