langxlang
Version:
LLM wrapper for OpenAI GPT and Google Gemini and PaLM 2 models
212 lines (204 loc) • 7.38 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LXL Log</title>
</head>
<style>
body {
font-family: sans-serif;
}
.message {
display: grid;
grid-template-columns: 160px calc(100vw - 160px);
margin-bottom: 1rem;
& pre {
white-space: break-spaces;
}
}
.role {
width: 160px;
}
a {
text-decoration: none;
}
</style>
<body>
<h3>LXL Session Log — <span id="session-date"></span></h3>
<hr>
<div id="messages"></div>
</body>
<script>
document.getElementById('session-date').innerText = window.$DATE || new Date().toDateString()
const messages = window.$ENTRIES || [
{ role: 'user', model: 'gemini-1.5-pro-latest', on: new Date(), messages: [{ role: 'user', parts: [{ text: 'Image test' }, { imageURL: 'https://imgs.xkcd.com/comics/standards.png' }] }] },
{ role: 'user', model: 'gemini-1.5-pro-latest', on: new Date(), messages: [{ role: 'user', text: 'Hello!' }] },
{ role: 'model', content: 'This\nworks', model: 'gemini-1.5-pro-latest', on: new Date().toLocaleString() },
{ role: 'model', content: [{ text: 'ok' }, { text: '!' }], model: 'gemini-1.5-pro-latest', on: new Date().toLocaleString() }
]
function addMessage({ role, author, model, on, content, messages, generationOptions = {} }, i) {
// const html = `
// <div class="message">
// <div class="role">
// <strong>Model</strong><br/>
// <small>${model}<br/>
// ${on}<br/>
// <a href="javascript:undefined">Copy Response</a>
// </small>
// </div>
// <div class="contents"><pre id="contents1">${str}</pre></div>
// </div>
// `
let contentHTML
function contentToHTML(content) {
let html = document.createElement('div')
if (typeof content === 'string') {
const pre = document.createElement('pre')
pre.innerText = content
html.appendChild(pre)
} else if (Array.isArray(content)) {
for (const part of content) {
if (part.imageURL || part.imageB64Url) {
if (part.imageB64Url) {
if (part.imageB64Url.startsWith('data:')) {
const img = document.createElement('img')
img.src = part.imageB64Url
html.appendChild(img)
continue
} else {
const mimeType = part.mimeType
const dataUrl = `data:${mimeType};base64,${part.imageB64Url}`
const img = document.createElement('img')
img.src = dataUrl
html.appendChild(img)
}
} else {
const img = document.createElement('img')
img.src = part.imageURL || part.imageB64Url
html.appendChild(img)
}
} else {
const pre = document.createElement('pre')
pre.innerText = part.text
html.appendChild(pre)
}
}
}
return html
}
if (role === 'user' && !content) {
contentHTML = document.createElement('div')
for (const message of messages) {
const messageDiv = document.createElement('div')
const roleEl = document.createElement('pre')
roleEl.innerText = `<|${message.role.toUpperCase()}|>`
messageDiv.appendChild(roleEl)
const contentEl = contentToHTML(message.parts || message.content)
messageDiv.appendChild(contentEl)
contentHTML.appendChild(messageDiv)
}
} else {
contentHTML = contentToHTML(content)
}
function onCopyContent() {
if (messages) {
const textContent = messages.map(message => typeof message.text
? message.text
: message.parts.map(part => part.text).join('\n')).join('\n')
navigator.clipboard.writeText(textContent)
} else {
const textContent = typeof content === 'string' ? content : content.map(part => part.text).join('\n')
navigator.clipboard.writeText(textContent)
}
}
function onCopyCode() {
function stringify(content, withPadding = '') {
return JSON.stringify(content, null, 2).split('\n').map((line, i) => i === 0 ? line : withPadding + line).join('\n')
}
const data = messages
? `
const { CompletionService } = require('langxlang')
async function main () {
const service = new CompletionService()
const [response] = await service.requestChatCompletion(${stringify(author, ' ')}, ${JSON.stringify(model)}, {
messages: ${stringify(messages, ' ')},
generationOptions: ${stringify(generationOptions || {}, ' ')}
})
console.log(response)
}
`.trim()
: `
const { CompletionService } = require('langxlang')
async function main () {
const service = new CompletionService()
const [response] = await service.requestCompletion(
${stringify(author, ' ')},
${stringify(model, ' ')},
'', /* system */
${stringify(content, ' ')}, /* user */
null, /* chunk cb */
${stringify(generationOptions || {}, ' ')} /* generate options */
)
console.log(response)
}
`.trim()
navigator.clipboard.writeText(data)
}
const buttons = role === 'user'
? [
['Copy Request JSON', () => navigator.clipboard.writeText(JSON.stringify(messages || content))],
['Copy Request MD', onCopyContent],
['Copy Replay Code', onCopyCode]
]
: [
['Copy Response', onCopyContent]
]
const roleName = role === 'user' ? 'Request' : 'Model'
const div = document.createElement('div')
div.className = 'message'
const roleEl = document.createElement('div')
roleEl.className = 'role'
const strong = document.createElement('strong')
strong.innerText = roleName
const small = document.createElement('small')
{
const modelEl = document.createElement('span')
modelEl.innerText = model
const onEl = document.createElement('span')
onEl.innerText = new Date(on).toLocaleString()
small.appendChild(modelEl)
small.appendChild(document.createElement('br'))
small.appendChild(onEl)
small.appendChild(document.createElement('br'))
if (role === 'model') for (const key in generationOptions) {
const optionEl = document.createElement('span')
optionEl.innerText = `*${key}: ${generationOptions[key]}`
small.appendChild(optionEl)
small.appendChild(document.createElement('br'))
}
for (const [name, action] of buttons) {
const copy = document.createElement('a')
copy.onclick = action
copy.href = 'javascript:undefined'
copy.innerText = name
small.appendChild(copy)
small.appendChild(document.createElement('br'))
}
}
roleEl.appendChild(strong)
roleEl.appendChild(document.createElement('br'))
roleEl.appendChild(small)
const contents = document.createElement('div')
contents.className = 'contents'
contentHTML.id = 'contents-' + i
contents.appendChild(contentHTML)
div.appendChild(roleEl)
div.appendChild(contents)
document.getElementById('messages').appendChild(div)
}
for (let i = 0; i < messages.length; i++) {
addMessage(messages[i], i)
}
</script>
</html>