ui: rebase and resolve conflict
This commit is contained in:
parent
0e18b2e7d0
commit
8cf2f35223
1 changed files with 289 additions and 192 deletions
|
@ -10,6 +10,7 @@
|
||||||
body {
|
body {
|
||||||
font-family: system-ui;
|
font-family: system-ui;
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#container {
|
#container {
|
||||||
|
@ -18,6 +19,7 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
@ -29,18 +31,15 @@
|
||||||
|
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
max-width: 600px;
|
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 0 0.5em;
|
padding: 0 0.5em;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
|
@ -142,6 +141,81 @@
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_controls {
|
||||||
|
gap: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexform {
|
||||||
|
display: flex;
|
||||||
|
max-height: 100%;
|
||||||
|
height: 100%;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
flex-grow: 1;
|
||||||
|
padding: 1rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aside {
|
||||||
|
max-width: 300px;
|
||||||
|
overflow: auto;
|
||||||
|
background: rgba(220, 220, 220, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width:600px) {
|
||||||
|
.aside {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.range_field {
|
||||||
|
border-bottom: 1px dashed;
|
||||||
|
padding-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range_field:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range_field label {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range_field input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.basecontainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.response p {
|
||||||
|
padding: 0.5em;
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.response p:nth-child(even) {
|
||||||
|
background-color: rgba(242, 242, 242, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
header,
|
header,
|
||||||
footer {
|
footer {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -150,8 +224,18 @@
|
||||||
footer {
|
footer {
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
color: #888;
|
color: #888;
|
||||||
|
box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(229, 231, 235, 0.53) 0px -1px 0px 0px, rgba(0, 0, 0, 0.24) 0px 5px 20px -5px;
|
||||||
|
padding-top: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media (max-width:600px) {
|
||||||
|
.footernote {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.mode-chat textarea[name=prompt] {
|
.mode-chat textarea[name=prompt] {
|
||||||
height: 4.5em;
|
height: 4.5em;
|
||||||
}
|
}
|
||||||
|
@ -615,7 +699,7 @@
|
||||||
return html`
|
return html`
|
||||||
<div id="chat" ref=${container} key=${messages.length}>
|
<div id="chat" ref=${container} key=${messages.length}>
|
||||||
<img style="width: 60%;${!session.value.image_selected ? `display: none;` : ``}" src="${session.value.image_selected}"/>
|
<img style="width: 60%;${!session.value.image_selected ? `display: none;` : ``}" src="${session.value.image_selected}"/>
|
||||||
<span contenteditable=${isCompletionMode} ref=${container} oninput=${handleCompletionEdit}>
|
<span class="response" contenteditable=${isCompletionMode} ref=${container} oninput=${handleCompletionEdit}>
|
||||||
${messages.flatMap(chatLine)}
|
${messages.flatMap(chatLine)}
|
||||||
</span>
|
</span>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
@ -649,20 +733,18 @@
|
||||||
|
|
||||||
const FloatField = ({ label, max, min, name, step, value }) => {
|
const FloatField = ({ label, max, min, name, step, value }) => {
|
||||||
return html`
|
return html`
|
||||||
<div>
|
<div class="range_field">
|
||||||
<label for="${name}">${label}</label>
|
<label for="${name}">${label} <span>${value}</span></label>
|
||||||
<input type="range" id="${name}" min="${min}" max="${max}" step="${step}" name="${name}" value="${value}" oninput=${updateParamsFloat} />
|
<input type="range" id="${name}" min="${min}" max="${max}" step="${step}" name="${name}" value="${value}" oninput=${updateParamsFloat} />
|
||||||
<span>${value}</span>
|
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
};
|
};
|
||||||
|
|
||||||
const IntField = ({ label, max, min, name, value }) => {
|
const IntField = ({ label, max, min, name, value }) => {
|
||||||
return html`
|
return html`
|
||||||
<div>
|
<div class="range_field">
|
||||||
<label for="${name}">${label}</label>
|
<label for="${name}">${label} <span>${value}</span></label>
|
||||||
<input type="range" id="${name}" min="${min}" max="${max}" name="${name}" value="${value}" oninput=${updateParamsInt} />
|
<input type="range" id="${name}" min="${min}" max="${max}" name="${name}" value="${value}" oninput=${updateParamsInt} />
|
||||||
<span>${value}</span>
|
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
};
|
};
|
||||||
|
@ -687,16 +769,17 @@
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// autosave template on every change
|
// autosave template on every change
|
||||||
userTemplateAutosave()
|
userTemplateAutosave()
|
||||||
}, [session.value, params.value])
|
}, [session.value])// removed params.value as it would re render the page.
|
||||||
|
|
||||||
const GrammarControl = () => (
|
const GrammarControl = () => (
|
||||||
html`
|
html`
|
||||||
<div>
|
<details>
|
||||||
|
<summary>Grammer Configuration</summary>
|
||||||
<label for="template">Grammar</label>
|
<label for="template">Grammar</label>
|
||||||
<textarea id="grammar" name="grammar" placeholder="Use gbnf or JSON Schema+convert" value="${params.value.grammar}" rows=4 oninput=${updateParams}/>
|
<textarea id="grammar" name="grammar" placeholder="Use gbnf or JSON Schema+convert" value="${params.value.grammar}" rows=4 oninput=${updateParams}/>
|
||||||
<input type="text" name="prop-order" placeholder="order: prop1,prop2,prop3" oninput=${updateGrammarJsonSchemaPropOrder} />
|
<input type="text" name="prop-order" placeholder="order: prop1,prop2,prop3" oninput=${updateGrammarJsonSchemaPropOrder} />
|
||||||
<button type="button" onclick=${convertJSONSchemaGrammar}>Convert JSON Schema</button>
|
<button type="button" onclick=${convertJSONSchemaGrammar}>Convert JSON Schema</button>
|
||||||
</div>
|
</details>
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -737,7 +820,6 @@
|
||||||
<label for="template">Chat history template</label>
|
<label for="template">Chat history template</label>
|
||||||
<textarea id="template" name="historyTemplate" value="${session.value.historyTemplate}" rows=1 oninput=${updateSession}/>
|
<textarea id="template" name="historyTemplate" value="${session.value.historyTemplate}" rows=1 oninput=${updateSession}/>
|
||||||
</div>
|
</div>
|
||||||
${GrammarControl()}
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
@ -745,23 +827,16 @@
|
||||||
const CompletionConfigForm = () => (
|
const CompletionConfigForm = () => (
|
||||||
html`
|
html`
|
||||||
${PromptControlFieldSet()}
|
${PromptControlFieldSet()}
|
||||||
<fieldset>${GrammarControl()}</fieldset>
|
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
|
||||||
return html`
|
|
||||||
<form>
|
|
||||||
<fieldset class="two">
|
|
||||||
<${UserTemplateResetButton}/>
|
|
||||||
<div>
|
|
||||||
<label class="slim"><input type="radio" name="type" value="chat" checked=${session.value.type === "chat"} oninput=${updateSession} /> Chat</label>
|
|
||||||
<label class="slim"><input type="radio" name="type" value="completion" checked=${session.value.type === "completion"} oninput=${updateSession} /> Completion</label>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
${session.value.type === 'chat' ? ChatConfigForm() : CompletionConfigForm()}
|
const ModelOptions = () => (
|
||||||
|
html`
|
||||||
|
|
||||||
<fieldset class="two">
|
<details>
|
||||||
|
<summary>Settings</summary>
|
||||||
|
<fieldset>
|
||||||
${IntField({ label: "Predictions", max: 2048, min: -1, name: "n_predict", value: params.value.n_predict })}
|
${IntField({ label: "Predictions", max: 2048, min: -1, name: "n_predict", value: params.value.n_predict })}
|
||||||
${FloatField({ label: "Temperature", max: 2.0, min: 0.0, name: "temperature", step: 0.01, value: params.value.temperature })}
|
${FloatField({ label: "Temperature", max: 2.0, min: 0.0, name: "temperature", step: 0.01, value: params.value.temperature })}
|
||||||
${FloatField({ label: "Penalize repeat sequence", max: 2.0, min: 0.0, name: "repeat_penalty", step: 0.01, value: params.value.repeat_penalty })}
|
${FloatField({ label: "Penalize repeat sequence", max: 2.0, min: 0.0, name: "repeat_penalty", step: 0.01, value: params.value.repeat_penalty })}
|
||||||
|
@ -769,17 +844,23 @@
|
||||||
${IntField({ label: "Top-K sampling", max: 100, min: -1, name: "top_k", value: params.value.top_k })}
|
${IntField({ label: "Top-K sampling", max: 100, min: -1, name: "top_k", value: params.value.top_k })}
|
||||||
${FloatField({ label: "Top-P sampling", max: 1.0, min: 0.0, name: "top_p", step: 0.01, value: params.value.top_p })}
|
${FloatField({ label: "Top-P sampling", max: 1.0, min: 0.0, name: "top_p", step: 0.01, value: params.value.top_p })}
|
||||||
${FloatField({ label: "Min-P sampling", max: 1.0, min: 0.0, name: "min_p", step: 0.01, value: params.value.min_p })}
|
${FloatField({ label: "Min-P sampling", max: 1.0, min: 0.0, name: "min_p", step: 0.01, value: params.value.min_p })}
|
||||||
|
${IntField({ label: "Show Probabilities", max: 10, min: 0, name: "n_probs", value: params.value.n_probs })}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
${GrammarControl()}
|
||||||
<details>
|
<details>
|
||||||
<summary>More options</summary>
|
<summary>More options</summary>
|
||||||
<fieldset class="two">
|
<fieldset>
|
||||||
${FloatField({ label: "TFS-Z", max: 1.0, min: 0.0, name: "tfs_z", step: 0.01, value: params.value.tfs_z })}
|
${FloatField({ label: "TFS-Z", max: 1.0, min: 0.0, name: "tfs_z", step: 0.01, value: params.value.tfs_z })}
|
||||||
${FloatField({ label: "Typical P", max: 1.0, min: 0.0, name: "typical_p", step: 0.01, value: params.value.typical_p })}
|
${FloatField({ label: "Typical P", max: 1.0, min: 0.0, name: "typical_p", step: 0.01, value: params.value.typical_p })}
|
||||||
${FloatField({ label: "Presence penalty", max: 1.0, min: 0.0, name: "presence_penalty", step: 0.01, value: params.value.presence_penalty })}
|
${FloatField({ label: "Presence penalty", max: 1.0, min: 0.0, name: "presence_penalty", step: 0.01, value: params.value.presence_penalty })}
|
||||||
${FloatField({ label: "Frequency penalty", max: 1.0, min: 0.0, name: "frequency_penalty", step: 0.01, value: params.value.frequency_penalty })}
|
${FloatField({ label: "Frequency penalty", max: 1.0, min: 0.0, name: "frequency_penalty", step: 0.01, value: params.value.frequency_penalty })}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<hr />
|
</details>
|
||||||
<fieldset class="three">
|
<details>
|
||||||
|
<summary>Mirostat</summary>
|
||||||
|
<fieldset>
|
||||||
<div>
|
<div>
|
||||||
<label><input type="radio" name="mirostat" value="0" checked=${params.value.mirostat == 0} oninput=${updateParamsInt} /> no Mirostat</label>
|
<label><input type="radio" name="mirostat" value="0" checked=${params.value.mirostat == 0} oninput=${updateParamsInt} /> no Mirostat</label>
|
||||||
<label><input type="radio" name="mirostat" value="1" checked=${params.value.mirostat == 1} oninput=${updateParamsInt} /> Mirostat v1</label>
|
<label><input type="radio" name="mirostat" value="1" checked=${params.value.mirostat == 1} oninput=${updateParamsInt} /> Mirostat v1</label>
|
||||||
|
@ -788,14 +869,31 @@
|
||||||
${FloatField({ label: "Mirostat tau", max: 10.0, min: 0.0, name: "mirostat_tau", step: 0.01, value: params.value.mirostat_tau })}
|
${FloatField({ label: "Mirostat tau", max: 10.0, min: 0.0, name: "mirostat_tau", step: 0.01, value: params.value.mirostat_tau })}
|
||||||
${FloatField({ label: "Mirostat eta", max: 1.0, min: 0.0, name: "mirostat_eta", step: 0.01, value: params.value.mirostat_eta })}
|
${FloatField({ label: "Mirostat eta", max: 1.0, min: 0.0, name: "mirostat_eta", step: 0.01, value: params.value.mirostat_eta })}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
|
||||||
${IntField({ label: "Show Probabilities", max: 10, min: 0, name: "n_probs", value: params.value.n_probs })}
|
|
||||||
</fieldset>
|
|
||||||
<fieldset>
|
|
||||||
<label for="api_key">API Key</label>
|
|
||||||
<input type="text" name="api_key" value="${params.value.api_key}" placeholder="Enter API key" oninput=${updateParams} />
|
|
||||||
</fieldset>
|
|
||||||
</details>
|
</details>
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
const ModeSelector = () => (
|
||||||
|
html`
|
||||||
|
<div class="header_controls">
|
||||||
|
<label class="slim"><input type="radio" name="type" value="chat" checked=${session.value.type === "chat"} oninput=${updateSession} /> Chat</label>
|
||||||
|
<label class="slim"><input type="radio" name="type" value="completion" checked=${session.value.type === "completion"} oninput=${updateSession} /> Completion</label>
|
||||||
|
<${UserTemplateResetButton}/>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
if (props?.header)
|
||||||
|
return html`<${ModeSelector} />`
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<form class="flexform">
|
||||||
|
<div class="column">
|
||||||
|
${session.value.type === 'chat' ? ChatConfigForm() : CompletionConfigForm()}
|
||||||
|
</div>
|
||||||
|
<div class="column aside">
|
||||||
|
<${ModelOptions} />
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
@ -880,7 +978,7 @@
|
||||||
}
|
}
|
||||||
return html`
|
return html`
|
||||||
<span>
|
<span>
|
||||||
${llamaStats.value.predicted_per_token_ms.toFixed()}ms per token, ${llamaStats.value.predicted_per_second.toFixed(2)} tokens per second
|
${llamaStats.value.predicted_per_token_ms.toFixed()}ms per token, ${llamaStats.value.predicted_per_second.toFixed(2)} tokens per second |
|
||||||
</span>
|
</span>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
@ -999,22 +1097,21 @@
|
||||||
function App(props) {
|
function App(props) {
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="mode-${session.value.type}">
|
<div class="basecontainer mode-${session.value.type}">
|
||||||
<header>
|
<header>
|
||||||
<h1>llama.cpp</h1>
|
<h1>llama.cpp</h1>
|
||||||
|
<${ConfigForm} header/>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main id="content">
|
<main id="content">
|
||||||
<${chatStarted.value ? ChatLog : ConfigForm} />
|
<${chatStarted.value ? ChatLog : ConfigForm} />
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
<section id="write">
|
<section id="write">
|
||||||
<${session.value.type === 'chat' ? MessageInput : CompletionControls} />
|
<${session.value.type === 'chat' ? MessageInput : CompletionControls} />
|
||||||
</section>
|
</section>
|
||||||
|
<p><${ModelGenerationInfo} /> <span class="footernote">Powered by <a href="https://github.com/ggerganov/llama.cpp">llama.cpp</a> and <a href="https://ggml.ai">ggml.ai</a></span></p>
|
||||||
<footer>
|
|
||||||
<p><${ModelGenerationInfo} /></p>
|
|
||||||
<p>Powered by <a href="https://github.com/ggerganov/llama.cpp">llama.cpp</a> and <a href="https://ggml.ai">ggml.ai</a>.</p>
|
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
@ -1022,6 +1119,7 @@
|
||||||
|
|
||||||
render(h(App), document.querySelector('#container'));
|
render(h(App), document.querySelector('#container'));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -1032,4 +1130,3 @@
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue