Spaces:
Runtime error
Runtime error
import json | |
from fasthtml.common import * | |
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") | |
fontlink = Link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.8.1/font/bootstrap-icons.min.css") | |
favicon = Link(rel="icon", type="image/x-icon", href="https://raw.githubusercontent.com/rajeshradhakrishnanmvk/aitemplate/main/favicon.ico") | |
title = Title("Groqlet Expendables") | |
css = Style("""body { | |
display: flex; | |
height: 100vh; | |
overflow: hidden; | |
} | |
#sidebar { | |
background-color: #f8f9fa; | |
padding: 10px; | |
overflow-y: auto; | |
height: 100vh; | |
} | |
#chat { | |
display: flex; | |
flex-direction: column; | |
height: 100vh; | |
overflow-y: hidden; | |
} | |
#chat-messages { | |
flex-grow: 1; | |
overflow-y: auto; | |
padding: 10px; | |
} | |
#chat-input { | |
padding: 10px; | |
border-top: 1px solid #e9ecef; | |
} | |
#documentsTab { | |
padding: 20px; | |
} | |
.file-upload { | |
display: none; | |
} | |
.file-icon { | |
width: 20px; | |
height: 20px; | |
} | |
.progress-bar { | |
width: 100%; | |
height: 100%; | |
background-color: #4caf50; | |
} | |
.container-fluid { | |
overflow-y: auto; | |
} | |
.form-label { | |
font-weight: bold; | |
} | |
.list-group-item { | |
cursor: pointer; | |
}""") | |
app = FastHTML(hdrs=(title,favicon,bootstraplink, fontlink,css)) | |
data = json.dumps([ | |
{ | |
"Persona": { | |
"agentname": "dinkan-1", | |
"metaprompt": "you are a helpful assistant", | |
"prefill": "helps me with financial Reconciliation", | |
"tooluse": "true", | |
"filesearch": "true", | |
"codeinterpreter": "true" | |
}, | |
"Plans": [ | |
{ "name": "askquestion", "createon": "06/8/2024", "tokencount": "2048" } | |
], | |
"Documents": [ | |
{ "file": "./reconciliation.txt", "createon": "06/8/2024", "size": "30,079", "Access": "private", "progress": "success" }, | |
{ "file": "./design.pdf", "createon": "07/8/2024", "size": "30,079", "Access": "public", "progress": "error" } | |
], | |
"Chat": [ | |
{"role": "system", "content":"Hello, thank you for democratizing AI's productivity benefits with open source! How can I help you today?"}, | |
{ "role": "assistant", "content": "what is the capital of India" }, | |
{ "role": "user", "content": "New Delhi is the capital of India" } | |
] | |
}, | |
{ | |
"Persona": { | |
"agentname": "dinkan-2", | |
"metaprompt": "you are a helpful assistant", | |
"prefill": "helps me with financial Reconciliation", | |
"tooluse": "true", | |
"filesearch": "false", | |
"codeinterpreter": "false" | |
}, | |
"Plans": [ | |
{ "name": "calculate", "createon": "07/8/2024", "tokencount": "1024" } | |
], | |
"Documents": [ | |
{ "file": "./design.txt", "createon": "08/8/2024", "size": "30,079", "Access": "private", "progress": "success" }, | |
{ "file": "./design.pdf", "createon": "09/8/2024", "size": "30,079", "Access": "public", "progress": "error" } | |
], | |
"Chat": [ | |
{"role": "system", "content":"Hello, thank you for democratizing AI's productivity benefits with open source! How can I help you today?"}, | |
{ "role": "assistant", "content": "what is the capital of Kerala" }, | |
{ "role": "user", "content": "Trivandrum is the capital of India" } | |
] | |
} | |
]) | |
def get(): | |
page = (Div( | |
Nav( | |
Div( | |
A("Groqlet Expendables", cls="navbar-brand", href="#"), | |
Div( | |
A( | |
I(cls="bi bi-plug"), | |
"Plugins", cls="nav-link text-white", href="#", style="margin-right: 10px;"), | |
A( | |
I(cls="bi bi-gear"), | |
"Settings", cls="nav-link text-white", href="#", style="margin-right: 10px;"), | |
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;") | |
,cls="d-flex align-items-center") | |
,cls="container-fluid") | |
,cls="navbar navbar-expand-lg navbar-dark",style="background-color: #800080;"), | |
Div( | |
Div( | |
Div( | |
H4("Agents"), | |
Button("+", cls="btn btn-primary btn-sm", id="addChatBtn") | |
, cls="d-flex justify-content-between align-items-center mb-2"), | |
Ul( | |
Li( | |
Div( | |
Span("Can you tell me a story?"), | |
Small("11:10 PM") | |
, cls="d-flex justify-content-between") | |
, cls="list-group-item") | |
, cls="list-group", id="chatList") | |
, cls="col-12 col-md-3", id="sidebar"), | |
Div( | |
A("Rename", cls="dropdown-item", href="#", id="renameItem") | |
,id="contextMenu", cls="dropdown-menu", style="display:none; position:absolute;"), | |
Div( | |
Ul( | |
Li( | |
A("Chat", cls="nav-link active", data_bs_toggle="tab", href="#chatTab") | |
, cls="nav-item"), | |
Li( | |
A("Documents", cls="nav-link", data_bs_toggle="tab", href="#documentsTab") | |
, cls="nav-item"), | |
Li( | |
A("Plans", cls="nav-link", data_bs_toggle="tab", href="#plansTab") | |
, cls="nav-item"), | |
Li( | |
A("Personas", cls="nav-link", data_bs_toggle="tab", href="#personasTab") | |
, cls="nav-item") | |
, cls="nav nav-tabs"), | |
Div( | |
Div( | |
Div( | |
Div( | |
Strong("Copilot"), | |
P("Hello, thank you for democratizing AI's productivity benefits with open source! How can I help you today?") | |
, cls="chat-message"), | |
Div( | |
Strong("MB"), | |
P("Can you tell me a story about a prince in a paragraph?") | |
, cls="chat-message") | |
, id="chat-messages"), | |
Div( | |
Input(type="text", cls="form-control me-2", placeholder="Type a message...", id="messageInput"), | |
Button("Send", cls="btn btn-primary", id="sendBtn") | |
, id="chat-input", cls="d-flex") | |
, cls="tab-pane fade show active", id="chatTab"), | |
Div( | |
Div( | |
H4("Documents"), | |
Button("Upload", cls="btn btn-primary btn-sm", id="uploadBtn"), | |
Input(type="file", id="fileInput", cls="file-upload") | |
, cls="d-flex justify-content-between align-items-center mb-2"), | |
Div( | |
Div( | |
Input(cls="form-check-input", type="radio", name="vectorDatabase", id="volatile", value="volatile"), | |
Label("Volatile", cls="form-check-label", _for="volatile") | |
, cls="form-check me-3"), | |
Div( | |
Input(cls="form-check-input", type="radio", name="vectorDatabase", id="textFile", value="textFile", checked=1), | |
Label("TextFile", cls="form-check-label", _for="textFile") | |
, cls="form-check me-3"), | |
Div( | |
Input(cls="form-check-input", type="radio", name="vectorDatabase", id="qdrant", value="qdrant"), | |
Label( "Qdrant", cls="form-check-label", _for="qdrant") | |
, cls="form-check me-3"), | |
Div( | |
Input(cls="form-check-input", type="radio", name="vectorDatabase", id="llamaindexSearch", value="llamaindexSearch"), | |
Label("llamaindex Search", cls="form-check-label", _for="llamaindexSearch") | |
, cls="form-check me-3") | |
,cls="d-flex mb-2"), | |
Table( | |
Thead(), | |
Tr( | |
Th("Name"), | |
Th("Created on"), | |
Th("Size (bytes)"), | |
Th("Access"), | |
Th("Progress")), | |
Tbody( | |
Tr( | |
Td(I(cls="bi bi-file-earmark-text file-icon"), " reconciliation.txt"), | |
Td("9:38 am"), | |
Td("30,079"), | |
Td("This chat"), | |
Td(Div(cls="progress"),Div(cls="progress-bar"))),id="fileTable"),cls="table") | |
,cls="tab-pane fade", id="documentsTab"), | |
Div( | |
Table( | |
Thead(), | |
Tr( | |
Th("Goal"), | |
Th("Created on"), | |
Th("Token Count")), | |
Tbody(id="planTable"), | |
Tr( | |
Td("askQuestions"), | |
Td("9:38 am"), | |
Td("30,079")),cls="table") | |
, cls="tab-pane fade", id="plansTab"), | |
Div( | |
Div( | |
H4("Persona"), | |
Div( | |
Label("Agent Name", cls="form-label", _for="agentNameInput"), | |
Input(type="text", cls="form-control", id="agentNameInput", placeholder="Enter your agent's name...") | |
, cls="mb-3"), | |
Div( | |
Label("Meta Prompt", cls="form-label", _for="metaPromptInput"), | |
Textarea(cls="form-control", id="metaPromptInput", rows="3", placeholder="Enter your Meta Prompt...") | |
, cls="mb-3"), | |
Div( | |
Label("Prefill", cls="form-label", _for="prefillInput"), | |
Textarea(cls="form-control", id="prefillInput", rows="3", placeholder="Enter agent's prefill...") | |
, cls="mb-3"), | |
Div( | |
Button("Save", cls="btn btn-primary", id="savePlanBtn") | |
, cls="d-flex justify-content-end"), | |
Hr(), | |
H5("Saved Plans"), | |
Ul(cls="list-group", id="savedPlansList") | |
, cls="container-fluid p-3") | |
, cls="tab-pane fade", id="personasTab") | |
, cls="tab-content flex-grow-1") | |
, cls="col-12 col-md-9 d-flex flex-column", id="chat") | |
, cls="row") | |
,cls="container-fluid"), | |
Script(src="https://code.jquery.com/jquery-3.6.0.min.js"), | |
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(f"let agents = {data};"), | |
Script(""" | |
let selectedAgentIndex = -1; | |
function populateTabs() { | |
if (selectedAgentIndex >= 0) { | |
const selectedAgent = agents[selectedAgentIndex]; | |
// Populate Personas tab | |
const agentNameInput = document.getElementById('agentNameInput'); | |
const metaPromptInput = document.getElementById('metaPromptInput'); | |
const prefillInput = document.getElementById('prefillInput'); | |
agentNameInput.value = agents[selectedAgentIndex].Persona.agentname; | |
metaPromptInput.value = agents[selectedAgentIndex].Persona.metaprompt; | |
prefillInput.value = agents[selectedAgentIndex].Persona.prefill; | |
// Populate Plans tab | |
// Clear and repopulate the plans table or list with selectedAgent.Plans | |
const planTable = document.getElementById('planTable'); | |
planTable.innerHTML = ''; | |
agents[selectedAgentIndex].Plans.forEach(plan => { | |
const newRow = `<tr> | |
<td>${plan.name}</td> | |
<td>${plan.createon}</td> | |
<td>${plan.tokencount}</td> | |
</tr>`; | |
planTable.insertAdjacentHTML('beforeend', newRow); | |
}); | |
// Populate Documents tab | |
// Clear and repopulate the documents table with selectedAgent.Documents | |
const fileTable = document.getElementById('fileTable'); | |
fileTable.innerHTML = ''; | |
agents[selectedAgentIndex].Documents.forEach(doc => { | |
const newRow = `<tr> | |
<td><i class="bi bi-file-earmark-text file-icon"></i> ${doc.file}</td> | |
<td>${doc.createon}</td> | |
<td>${doc.size}</td> | |
<td>${doc.Access}</td> | |
<td><div class="progress"><div class="progress-bar"></div></div></td> | |
</tr>`; | |
fileTable.insertAdjacentHTML('beforeend', newRow); | |
}); | |
// Display initial messages | |
//displayMessages(); | |
} | |
} | |
function renderChatList() { | |
const chatList = document.getElementById('chatList'); | |
chatList.innerHTML = ''; // Clear the existing list | |
agents.forEach((agent, index) => { | |
const newItem = document.createElement('li'); | |
newItem.className = 'list-group-item'; | |
newItem.innerHTML = `<div class="d-flex justify-content-between"> | |
<span>${agent.Persona.agentname}</span> | |
<small>${new Date().toLocaleTimeString()}</small> | |
</div>`; | |
newItem.setAttribute('data-index', index); | |
newItem.setAttribute('data-messages', JSON.stringify(agent.Chat)); | |
newItem.addEventListener('click', function() { | |
selectedAgentIndex = parseInt(this.getAttribute('data-index')); | |
displayMessages(); | |
populateTabs(); | |
}); | |
newItem.addEventListener('contextmenu', function(e) { | |
e.preventDefault(); | |
showContextMenu(e, newItem, index); | |
}); | |
chatList.appendChild(newItem); | |
}); | |
} | |
// Event listener for add chat button - Sidebar | |
document.getElementById('addChatBtn').addEventListener('click', function() { | |
var chatList = document.getElementById('chatList'); | |
var newItem = document.createElement('li'); | |
newItem.className = 'list-group-item'; | |
newItem.innerHTML = `<div class="d-flex justify-content-between"> | |
<span>New Agent</span> | |
<small>${new Date().toLocaleTimeString()}</small> | |
</div>`; | |
newItem.setAttribute('data-messages', JSON.stringify([])); | |
chatList.appendChild(newItem); | |
// Add new agent to agents array | |
var newAgent = { | |
"Persona": { | |
"agentname": `agent-${Date.now()}`, | |
"metaprompt": "you are a helpful assistant", | |
"prefill": "helps me with financial Reconciliation", | |
"tooluse": "true", | |
"filesearch": "false", | |
"codeinterpreter": "false" | |
}, | |
"Plans": [], | |
"Documents": [], | |
"Chat": [] | |
}; | |
agents.push(newAgent); | |
renderChatList(); | |
}); | |
// Show context menu | |
function showContextMenu(event, listItem) { | |
var contextMenu = document.getElementById('contextMenu'); | |
contextMenu.style.display = 'block'; | |
contextMenu.style.left = event.pageX + 'px'; | |
contextMenu.style.top = event.pageY + 'px'; | |
document.getElementById('renameItem').onclick = function() { | |
var newName = prompt("Enter new name:", listItem.querySelector('span').textContent); | |
if (newName) { | |
listItem.querySelector('span').textContent = newName; | |
//write a code to update the agent name in agents array | |
agents[selectedAgentIndex].Persona.agentname = newName; | |
} | |
contextMenu.style.display = 'none'; | |
}; | |
document.addEventListener('click', function() { | |
contextMenu.style.display = 'none'; | |
}, { once: true }); | |
} | |
// Event listener for existing items | |
document.querySelectorAll('#chatList .list-group-item').forEach(item => { | |
item.addEventListener('contextmenu', function(e) { | |
e.preventDefault(); | |
showContextMenu(e, item); | |
}); | |
}); | |
// Function to display messages | |
function displayMessages() { | |
const chatMessages = document.getElementById('chat-messages'); | |
chatMessages.innerHTML = ''; | |
agents[selectedAgentIndex].Chat.forEach(msg => { | |
const messageElement = document.createElement('div'); | |
messageElement.classList.add('chat-message'); | |
messageElement.innerHTML = `<strong>${msg.role}</strong><p>${msg.content}</p>`; | |
chatMessages.appendChild(messageElement); | |
}); | |
} | |
// Event listener for sidebar items | |
document.querySelectorAll('#chatList .list-group-item').forEach(item => { | |
item.addEventListener('click', function() { | |
const newMessages = JSON.parse(this.getAttribute('data-messages')); | |
messages = [...newMessages]; | |
displayMessages(); | |
}); | |
}); | |
// Event listener for send button | |
document.getElementById('sendBtn').addEventListener('click', function() { | |
const input = document.getElementById('messageInput'); | |
const userMessage = input.value; | |
if (userMessage) { | |
agents[selectedAgentIndex].Chat.push({ role: 'MB', content: userMessage }); | |
if (userMessage.toLowerCase() === 'what is the capital of india') { | |
agents[0].Chat.push({ role: 'Copilot', content: 'New Delhi is the capital of India' }); | |
} | |
displayMessages(); | |
input.value = ''; | |
} | |
}); | |
// Event listener for upload button | |
document.getElementById('uploadBtn').addEventListener('click', function() { | |
document.getElementById('fileInput').click(); | |
}); | |
// Event listener for file input - Documents Tab | |
document.getElementById('fileInput').addEventListener('change', function(event) { | |
const file = event.target.files[0]; | |
if (file) { | |
const newRow = `<tr> | |
<td><i class="bi bi-file-earmark-text file-icon"></i> ${file.name}</td> | |
<td>${new Date().toLocaleTimeString()}</td> | |
<td>${file.size}</td> | |
<td>This chat</td> | |
<td><div class="progress"><div class="progress-bar"></div></div></td> | |
</tr>`; | |
document.getElementById('fileTable').insertAdjacentHTML('beforeend', newRow); | |
} | |
}); | |
// Event listener for save button - Personas Tab | |
document.getElementById('savePlanBtn').addEventListener('click', function() { | |
const agentname = document.getElementById('agentNameInput').value; | |
const metaprompt = document.getElementById('metaPromptInput').value; | |
const prefill = document.getElementById('prefillInput').value; | |
const plan = { | |
agentname, | |
metaprompt, | |
prefill | |
}; | |
const savedPlansList = document.getElementById('savedPlansList'); | |
const planItem = document.createElement('li'); | |
planItem.classList.add('list-group-item'); | |
planItem.textContent = `Agent Name: ${agentname}`; | |
planItem.addEventListener('click', function() { | |
alert(`Meta Prompt: ${plan.metaprompt}\nPrefill: ${plan.prefill}`); | |
}); | |
savedPlansList.appendChild(planItem); | |
// Clear the inputs after saving | |
document.getElementById('agentNameInput').value = ''; | |
document.getElementById('metaPromptInput').value = ''; | |
document.getElementById('prefillInput').value = ''; | |
}); | |
// Initial rendering of the chat list | |
renderChatList(); | |
// Populate tabs initially (if needed) | |
populateTabs(); | |
""")) | |
return page | |
serve() | |