|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8" /> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
<title>LLM Open Connector Tester for GROQ</title> |
|
<link |
|
rel="icon" |
|
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🤖</text></svg>" |
|
/> |
|
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script> |
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> |
|
<link |
|
rel="stylesheet" |
|
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/default.min.css" |
|
/> |
|
<link |
|
rel="stylesheet" |
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" |
|
/> |
|
<style> |
|
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700&display=swap"); |
|
|
|
:root { |
|
--primary-color: #4a90e2; |
|
--secondary-color: #f5f5f5; |
|
--text-color: #333; |
|
--border-radius: 8px; |
|
--transition-speed: 0.3s; |
|
--charcoal: #36454f; |
|
--charcoal-light: #485a66; |
|
--charcoal-lighter: #5a6e7a; |
|
--charcoal-dark: #2c3a42; |
|
--charcoal-darker: #232e35; |
|
} |
|
|
|
body { |
|
font-family: "Open Sans", sans-serif; |
|
font-weight: 400; |
|
line-height: 1.6; |
|
color: var(--text-color); |
|
max-width: 800px; |
|
margin: 0 auto; |
|
padding: 20px; |
|
background-color: #f0f4f8; |
|
transition: background-color var(--transition-speed) ease; |
|
} |
|
|
|
body.dark-mode { |
|
--primary-color: #64b5f6; |
|
--secondary-color: #2c2c2c; |
|
--text-color: #e0e0e0; |
|
background-color: var(--charcoal-darker); |
|
} |
|
|
|
.header { |
|
display: flex; |
|
align-items: center; |
|
justify-content: space-between; |
|
margin-bottom: 30px; |
|
} |
|
|
|
.logo { |
|
display: flex; |
|
align-items: center; |
|
font-size: 24px; |
|
color: var(--text-color); |
|
font-weight: 600; |
|
} |
|
|
|
.logo i { |
|
margin-right: 10px; |
|
} |
|
|
|
h1 { |
|
color: var(--text-color); |
|
margin: 0; |
|
font-weight: 700; |
|
} |
|
|
|
.dark-mode-toggle { |
|
background: none; |
|
border: none; |
|
color: var(--text-color); |
|
font-size: 20px; |
|
cursor: pointer; |
|
} |
|
|
|
form { |
|
background-color: var(--secondary-color); |
|
padding: 20px; |
|
border-radius: var(--border-radius); |
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); |
|
margin-bottom: 20px; |
|
} |
|
|
|
.input-container { |
|
position: relative; |
|
margin-bottom: 10px; |
|
} |
|
|
|
textarea { |
|
width: 100%; |
|
height: 120px; |
|
padding: 10px; |
|
border: 1px solid #ddd; |
|
border-radius: var(--border-radius); |
|
resize: vertical; |
|
font-size: 16px; |
|
font-family: "Open Sans", sans-serif; |
|
background-color: var(--secondary-color); |
|
color: var(--text-color); |
|
} |
|
|
|
.char-count { |
|
position: absolute; |
|
bottom: 5px; |
|
right: 10px; |
|
font-size: 12px; |
|
color: #888; |
|
} |
|
|
|
.button-container { |
|
display: flex; |
|
justify-content: space-between; |
|
} |
|
|
|
button { |
|
padding: 10px 20px; |
|
background-color: var(--primary-color); |
|
color: white; |
|
border: none; |
|
border-radius: var(--border-radius); |
|
font-size: 16px; |
|
font-family: "Open Sans", sans-serif; |
|
font-weight: 600; |
|
cursor: pointer; |
|
transition: background-color var(--transition-speed) ease; |
|
} |
|
|
|
button:hover { |
|
background-color: var(--charcoal-light); |
|
} |
|
|
|
#clearButton { |
|
background-color: var(--charcoal-light); |
|
color: white; |
|
} |
|
|
|
#clearButton:hover { |
|
background-color: var(--charcoal-lighter); |
|
} |
|
|
|
#response { |
|
background-color: var(--secondary-color); |
|
padding: 20px; |
|
border-radius: var(--border-radius); |
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); |
|
font-size: 16px; |
|
transition: all var(--transition-speed) ease; |
|
overflow-x: auto; |
|
min-height: 100px; |
|
line-height: 1.6; |
|
} |
|
|
|
#response h1, |
|
#response h2, |
|
#response h3, |
|
#response h4, |
|
#response h5, |
|
#response h6 { |
|
margin-top: 1.5em; |
|
margin-bottom: 0.5em; |
|
color: var(--text-color); |
|
} |
|
|
|
#response p { |
|
margin-bottom: 1em; |
|
} |
|
|
|
#response ul, |
|
#response ol { |
|
margin-bottom: 1em; |
|
padding-left: 2em; |
|
} |
|
|
|
#response li { |
|
margin-bottom: 0.5em; |
|
} |
|
|
|
#response pre { |
|
background-color: #f4f4f4; |
|
padding: 1em; |
|
border-radius: 4px; |
|
overflow-x: auto; |
|
margin-bottom: 1em; |
|
} |
|
|
|
#response code { |
|
font-family: "Courier New", Courier, monospace; |
|
font-size: 0.9em; |
|
padding: 0.2em 0.4em; |
|
background-color: #f0f0f0; |
|
border-radius: 3px; |
|
} |
|
|
|
#response pre code { |
|
padding: 0; |
|
background-color: transparent; |
|
} |
|
|
|
#response blockquote { |
|
border-left: 4px solid var(--primary-color); |
|
padding-left: 1em; |
|
margin-left: 0; |
|
margin-bottom: 1em; |
|
font-style: italic; |
|
color: #666; |
|
} |
|
|
|
#response table { |
|
border-collapse: collapse; |
|
width: 100%; |
|
margin-bottom: 1em; |
|
} |
|
|
|
#response th, |
|
#response td { |
|
border: 1px solid #ddd; |
|
padding: 8px; |
|
text-align: left; |
|
} |
|
|
|
#response th { |
|
background-color: #f4f4f4; |
|
font-weight: bold; |
|
} |
|
|
|
.default-message { |
|
color: #888; |
|
font-style: italic; |
|
} |
|
|
|
.loading { |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
height: 100px; |
|
} |
|
|
|
.spinner { |
|
border: 4px solid rgba(0, 0, 0, 0.1); |
|
border-left-color: var(--primary-color); |
|
border-radius: 50%; |
|
width: 40px; |
|
height: 40px; |
|
animation: spin 1s linear infinite; |
|
} |
|
|
|
@keyframes spin { |
|
0% { |
|
transform: rotate(0deg); |
|
} |
|
100% { |
|
transform: rotate(360deg); |
|
} |
|
} |
|
|
|
@media (max-width: 600px) { |
|
body { |
|
padding: 10px; |
|
} |
|
} |
|
|
|
|
|
.endpoint-selection { |
|
margin-bottom: 20px; |
|
} |
|
|
|
.endpoint-selection label { |
|
margin: 0 15px; |
|
display: flex; |
|
align-items: center; |
|
font-size: 16px; |
|
color: var(--text-color); |
|
cursor: pointer; |
|
} |
|
|
|
.endpoint-selection input[type="radio"] { |
|
margin-right: 8px; |
|
accent-color: var(--primary-color); |
|
} |
|
|
|
|
|
body.dark-mode .endpoint-selection input[type="radio"] { |
|
background-color: var(--secondary-color); |
|
border-color: var(--text-color); |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="header"> |
|
<div class="logo"> |
|
<i class="fas fa-robot"></i> |
|
<h1>LLM Open Connector Tester</h1> |
|
</div> |
|
|
|
<button id="darkModeToggle" class="dark-mode-toggle"> |
|
<i class="fas fa-moon"></i> |
|
</button> |
|
</div> |
|
|
|
<p> |
|
Test your implementation of Salesforce’s |
|
<a |
|
href="https://github.com/salesforce/einstein-platform?tab=readme-ov-file#llm-open-connector" |
|
>LLM Open Connector For Groq</a |
|
> |
|
with <a href="https://groq.com/">Groq</a>. |
|
</p> |
|
|
|
<form id="promptForm"> |
|
<div class="input-container"> |
|
<textarea |
|
id="prompt" |
|
placeholder="Enter your prompt here..." |
|
></textarea> |
|
<div class="char-count">0 / 500</div> |
|
</div> |
|
|
|
|
|
<p>Endpoint to test:</p> |
|
|
|
<div class="endpoint-selection"> |
|
<label> |
|
<input type="radio" name="endpoint" value="chat" checked /> |
|
<code>/chat/completions</code> |
|
</label> |
|
<label> |
|
<input type="radio" name="endpoint" value="completion" /> |
|
<code>/completions</code> |
|
</label> |
|
</div> |
|
|
|
<div class="button-container"> |
|
<button type="submit">Generate Response</button> |
|
<button type="button" id="clearButton">Clear</button> |
|
</div> |
|
</form> |
|
<div id="response"></div> |
|
|
|
<script> |
|
const darkModeToggle = document.getElementById("darkModeToggle"); |
|
const body = document.body; |
|
const promptTextarea = document.getElementById("prompt"); |
|
const charCount = document.querySelector(".char-count"); |
|
const clearButton = document.getElementById("clearButton"); |
|
const form = document.getElementById("promptForm"); |
|
const responseDiv = document.getElementById("response"); |
|
const defaultMessage = |
|
'<div class="default-message">Your generated response will appear here. Enter a prompt above and click "Generate Response" to start.</div>'; |
|
|
|
|
|
responseDiv.innerHTML = defaultMessage; |
|
|
|
darkModeToggle.addEventListener("click", () => { |
|
body.classList.toggle("dark-mode"); |
|
darkModeToggle.innerHTML = body.classList.contains("dark-mode") |
|
? '<i class="fas fa-sun"></i>' |
|
: '<i class="fas fa-moon"></i>'; |
|
}); |
|
|
|
promptTextarea.addEventListener("input", () => { |
|
const length = promptTextarea.value.length; |
|
charCount.textContent = `${length} / 500`; |
|
}); |
|
|
|
|
|
promptTextarea.addEventListener("keydown", (e) => { |
|
if (e.key === "Enter" && !e.shiftKey) { |
|
e.preventDefault(); |
|
form.dispatchEvent(new Event("submit")); |
|
} |
|
}); |
|
|
|
clearButton.addEventListener("click", () => { |
|
promptTextarea.value = ""; |
|
responseDiv.innerHTML = defaultMessage; |
|
charCount.textContent = "0 / 500"; |
|
}); |
|
|
|
form.addEventListener("submit", async (e) => { |
|
e.preventDefault(); |
|
const prompt = promptTextarea.value.trim(); |
|
if (!prompt) return; |
|
|
|
responseDiv.innerHTML = |
|
'<div class="loading"><div class="spinner"></div></div>'; |
|
const API_GATEWAY_URL = "https://einsteincoder-llm-open-connector-groq.hf.space"; |
|
|
|
|
|
const endpoint = document.querySelector( |
|
'input[name="endpoint"]:checked' |
|
).value; |
|
|
|
let url = ""; |
|
let data = {}; |
|
|
|
if (endpoint === "chat") { |
|
url = `${API_GATEWAY_URL}/chat/completions`; |
|
data = { |
|
messages: [{ role: "user", content: prompt }], |
|
temperature: 0.5, |
|
max_tokens: 1000, |
|
}; |
|
} else { |
|
url = `${API_GATEWAY_URL}/completions`; |
|
data = { |
|
prompt: prompt, |
|
temperature: 0.5, |
|
max_tokens: 1000, |
|
}; |
|
} |
|
|
|
try { |
|
const response = await axios.post(url, data, { |
|
headers: { |
|
"api-key": "Einstein1234$", |
|
}, |
|
}); |
|
|
|
let content = ""; |
|
|
|
if (endpoint === "chat") { |
|
content = response.data.choices[0].message.content; |
|
} else { |
|
content = response.data.choices[0].text; |
|
} |
|
|
|
|
|
const parsedContent = marked.parse(content); |
|
|
|
|
|
responseDiv.innerHTML = parsedContent; |
|
|
|
|
|
document.querySelectorAll("pre code").forEach((block) => { |
|
hljs.highlightElement(block); |
|
}); |
|
} catch (error) { |
|
responseDiv.textContent = "Error: " + error.message; |
|
} |
|
}); |
|
|
|
|
|
hljs.highlightAll(); |
|
</script> |
|
</body> |
|
</html> |