Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 99a7ea2

Browse files
authoredFeb 25, 2025··
Merge pull request #314 from iceljc/features/refine-chat-window
refine instruction page
2 parents 0b67f8f + 582c0e7 commit 99a7ea2

File tree

6 files changed

+354
-335
lines changed

6 files changed

+354
-335
lines changed
 

‎src/lib/scss/custom/pages/_instruction.scss

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
}
4949

5050
.instruction-gap {
51-
margin-top: 10px;
51+
margin-top: 30px;
5252
}
5353
}
5454

@@ -79,7 +79,7 @@
7979

8080
.instruct-state-item {
8181
display: flex;
82-
gap: 10px;
82+
gap: 30px;
8383
justify-content: center;
8484
}
8585
}

‎src/routes/page/instruction/+page.svelte

+106-46
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,33 @@
33
import { fly } from 'svelte/transition';
44
import { _ } from 'svelte-i18n';
55
import util from "lodash";
6-
import { Button, Col, Row } from '@sveltestrap/sveltestrap';
6+
import { Button, Card, CardBody, Col, Row } from '@sveltestrap/sveltestrap';
77
import LoadingDots from '$lib/common/LoadingDots.svelte';
88
import HeadTitle from '$lib/common/HeadTitle.svelte';
99
import Breadcrumb from '$lib/common/Breadcrumb.svelte';
1010
import Markdown from '$lib/common/markdown/Markdown.svelte';
11-
import InstructionSetting from './instruction-components/instruction-setting.svelte';
1211
import InstructionState from './instruction-components/instruction-state.svelte';
1312
import { getAgents } from '$lib/services/agent-service';
1413
import LoadingToComplete from '$lib/common/LoadingToComplete.svelte';
1514
import { sendChatCompletion } from '$lib/services/instruct-service';
1615
import { getLlmConfigs } from '$lib/services/llm-provider-service';
1716
import { LlmModelType } from '$lib/helpers/enums';
17+
import NavBar from '$lib/common/nav-bar/NavBar.svelte';
18+
import NavItem from '$lib/common/nav-bar/NavItem.svelte';
19+
import InstructionTemplate from './instruction-components/instruction-template.svelte';
20+
import InstructionLlm from './instruction-components/instruction-llm.svelte';
1821
1922
const maxLength = 64000;
2023
const DEFAULT_PROVIDER = 'openai';
2124
const DEFAULT_MODEL = 'gpt-4o-mini';
2225
26+
/** @type {any[]}*/
27+
const tabs = [
28+
{ name: 'instruction-template', displayText: 'Template' },
29+
{ name: 'instruction-llm', displayText: 'LLM Config' },
30+
{ name: 'instruction-states', displayText: 'States' }
31+
];
32+
2333
let isLoading = false;
2434
let isThinking = false;
2535
let requestDone = false;
@@ -32,7 +42,7 @@
3242
/** @type {import('$agentTypes').AgentModel | null} */
3343
let selectedAgent = null;
3444
35-
/** @type {string | null} */
45+
/** @type {import('$commonTypes').LlmConfig?} */
3646
let selectedProvider = null;
3747
3848
/** @type {string | null} */
@@ -49,6 +59,9 @@
4959
{ key: '', value: ''}
5060
];
5161
62+
/** @type {string}*/
63+
let selectedTab = tabs[0].name;
64+
5265
onMount(async () => {
5366
try {
5467
isLoading = true;
@@ -62,7 +75,6 @@
6275
}
6376
});
6477
65-
6678
function sendRequest() {
6779
isThinking = true;
6880
requestDone = false;
@@ -73,7 +85,7 @@
7385
text: util.trim(text) || '',
7486
instruction: util.trim(instruction) || null,
7587
agentId: selectedAgent?.id,
76-
provider: selectedProvider || DEFAULT_PROVIDER,
88+
provider: selectedProvider?.provider || DEFAULT_PROVIDER,
7789
model: selectedModel || DEFAULT_MODEL,
7890
states: formattedStates
7991
}).then(res => {
@@ -121,21 +133,29 @@
121133
122134
/** @param {any} e */
123135
function onAgentSelected(e) {
124-
selectedAgent = e.detail.selectedAgent || null;
136+
selectedAgent = e.detail.agent || null;
125137
instruction = selectedAgent?.instruction || '';
126138
127-
const template = e.detail.selectedTemplate || null;
139+
const template = e.detail.template || null;
128140
if (!!template) {
129141
instruction = template?.content || '';
130142
}
131143
132-
onLlmSelected(e);
144+
const providerName = selectedAgent?.llm_config?.provider || null;
145+
const modelName = selectedAgent?.llm_config?.model || null;
146+
selectedProvider = llmConfigs?.find(x => x.provider === providerName) || null;
147+
selectedModel = modelName;
133148
}
134149
135150
/** @param {any} e */
136151
function onLlmSelected(e) {
137-
selectedProvider = e.detail.selectedProvider || null;
138-
selectedModel = e.detail.selectedModel || '';
152+
selectedProvider = e.detail.provider || null;
153+
selectedModel = e.detail.model || '';
154+
}
155+
156+
/** @param {string} selected */
157+
function handleTabClick(selected) {
158+
selectedTab = selected;
139159
}
140160
</script>
141161
@@ -151,7 +171,7 @@
151171
rows={8}
152172
maxlength={maxLength}
153173
disabled={isThinking}
154-
placeholder={'Start typing here...'}
174+
placeholder={'Enter input message...'}
155175
bind:value={text}
156176
on:keydown={(e) => pressKey(e)}
157177
/>
@@ -207,55 +227,95 @@
207227
</div>
208228
</div>
209229
210-
211-
<div class="d-xl-flex mt-3">
212-
<div class="w-100">
213-
<InstructionSetting
214-
disabled={isThinking}
215-
agents={agents}
216-
llmConfigs={llmConfigs}
217-
on:agentSelected={e => onAgentSelected(e)}
218-
on:llmSelected={e => onLlmSelected(e)}
219-
/>
220-
</div>
221-
</div>
222-
223-
224230
<div class="d-xl-flex mt-4 mb-5">
225231
<div class="w-100">
232+
<Row>
233+
<Col lg="7">
234+
<div class="instruct-text-header text-primary fw-bold mb-2">
235+
<div class="line-align-center">
236+
{'Instruction'}
237+
</div>
238+
<div class="line-align-center">
239+
<!-- svelte-ignore a11y-click-events-have-key-events -->
240+
<!-- svelte-ignore a11y-no-static-element-interactions -->
241+
<i
242+
class="mdi mdi-refresh text-primary clickable"
243+
data-bs-toggle="tooltip"
244+
data-bs-placement="bottom"
245+
title={'Reset'}
246+
on:click={e => resetInstruction()}
247+
/>
248+
</div>
249+
</div>
250+
</Col>
251+
<Col lg="5"></Col>
252+
</Row>
226253
<Row class="instruct-setting-container">
227-
<Col lg="9">
254+
<Col lg="7">
228255
<div>
229-
<div class="instruct-text-header text-primary fw-bold mb-2">
230-
<div class="line-align-center">
231-
{'Instruction'}
232-
</div>
233-
<div class="line-align-center">
234-
<!-- svelte-ignore a11y-click-events-have-key-events -->
235-
<!-- svelte-ignore a11y-no-static-element-interactions -->
236-
<i
237-
class="mdi mdi-refresh text-primary clickable"
238-
data-bs-toggle="tooltip"
239-
data-bs-placement="bottom"
240-
title={'Reset'}
241-
on:click={e => resetInstruction()}
242-
/>
243-
</div>
244-
</div>
245-
<div class="instruct-setting-section instruction-border instruct-setting-padding">
256+
<div class="instruct-setting-section" style="gap: 2px;">
246257
<textarea
247258
class='form-control knowledge-textarea'
248259
rows={19}
249260
maxlength={maxLength}
250261
disabled={isThinking}
251-
placeholder={'Start typing here...'}
262+
placeholder={'Enter instruction...'}
252263
bind:value={instruction}
253264
/>
265+
<div class="text-secondary text-end text-count">
266+
<div>{instruction?.length || 0}/{maxLength}</div>
267+
</div>
254268
</div>
255269
</div>
256270
</Col>
257-
<Col lg="3">
258-
<InstructionState bind:states={states} disabled={isThinking} />
271+
<Col lg="5" class="instruction-gap">
272+
<Card>
273+
<CardBody>
274+
275+
<NavBar
276+
id={'instruction-nav-container'}
277+
disableDefaultStyles
278+
containerClasses={'nav-tabs-secondary'}
279+
>
280+
{#each tabs as tab, idx}
281+
<NavItem
282+
containerStyles={`flex: 0 1 calc(100% / ${tabs.length <= 2 ? tabs.length : 3})`}
283+
navBtnStyles={'text-transform: none;'}
284+
navBtnId={`${tab.name}-tab`}
285+
dataBsTarget={`#${tab.name}-tab-pane`}
286+
ariaControls={`${tab.name}-tab-pane`}
287+
navBtnText={tab.displayText}
288+
active={tab.name === selectedTab}
289+
onClick={() => handleTabClick(tab.name)}
290+
/>
291+
{/each}
292+
</NavBar>
293+
294+
<div class:hide={selectedTab !== 'instruction-template'}>
295+
<InstructionTemplate
296+
agents={agents}
297+
disabled={isThinking}
298+
on:agentSelected={e => onAgentSelected(e)}
299+
/>
300+
</div>
301+
<div class:hide={selectedTab !== 'instruction-llm'}>
302+
<InstructionLlm
303+
llmConfigs={llmConfigs}
304+
disabled={isThinking}
305+
selectedProvider={selectedProvider}
306+
selectedModel={selectedModel}
307+
on:llmSelected={e => onLlmSelected(e)}
308+
/>
309+
</div>
310+
<div class:hide={selectedTab !== 'instruction-states'}>
311+
<InstructionState
312+
bind:states={states}
313+
disabled={isThinking}
314+
/>
315+
</div>
316+
</CardBody>
317+
</Card>
318+
259319
</Col>
260320
</Row>
261321
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<script>
2+
import { afterUpdate, createEventDispatcher, onMount } from 'svelte';
3+
import { _ } from 'svelte-i18n';
4+
5+
const svelteDispatch = createEventDispatcher();
6+
7+
/** @type {import('$commonTypes').LlmConfig[]} */
8+
export let llmConfigs = [];
9+
10+
/** @type {boolean} */
11+
export let disabled = false;
12+
13+
/** @type {import('$commonTypes').LlmConfig?} */
14+
export let selectedProvider = null;
15+
16+
/** @type {any} */
17+
export let selectedModel = null;
18+
19+
/** @type {any[]} */
20+
let providerOptions = [];
21+
/** @type {any[]} */
22+
let modelOptions = [];
23+
24+
afterUpdate(() => {
25+
if (selectedProvider) {
26+
onProviderChanged();
27+
}
28+
});
29+
30+
$: {
31+
collectLlmOptions(llmConfigs);
32+
}
33+
34+
/** @param {import('$commonTypes').LlmConfig[]} llmConfigs */
35+
function collectLlmOptions(llmConfigs) {
36+
providerOptions = llmConfigs?.map(x => ({
37+
id: x.provider,
38+
name: x.provider
39+
}))?.sort((a, b) => a.name.localeCompare(b.name)) || [];
40+
}
41+
42+
/** @param {any} e */
43+
function selectProvider(e) {
44+
const selected = e.target.value || null;
45+
selectedProvider = llmConfigs?.find(x => x.provider === selected) || null;
46+
onProviderChanged();
47+
console.log(selectedModel, modelOptions);
48+
disPatchEvent();
49+
}
50+
51+
/** @param {any} e */
52+
function selectModel(e) {
53+
const selected = e.target.value || null;
54+
selectedModel = modelOptions.find(x => x.id === selected);
55+
disPatchEvent();
56+
}
57+
58+
/** @param {any?} targetModel */
59+
function onProviderChanged(targetModel = null) {
60+
modelOptions = selectedProvider?.models?.map(x => ({
61+
id: x.name,
62+
name: x.name
63+
}))?.sort((a, b) => a.name.localeCompare(b.name)) || [];
64+
65+
if (!!targetModel) {
66+
selectedModel = modelOptions.find(x => x.name === targetModel) || null;
67+
} else {
68+
selectedModel = modelOptions.length > 0 ? modelOptions[0] : null;
69+
}
70+
}
71+
72+
function disPatchEvent() {
73+
svelteDispatch('llmSelected', {
74+
provider: selectedProvider,
75+
model: selectedModel?.name
76+
});
77+
}
78+
</script>
79+
80+
81+
<div class="instruct-setting-section instruct-setting-padding">
82+
<div class="instruct-setting-item">
83+
<div class="instruct-setting-dropdown">
84+
<div class="text-primary fw-bold mb-1">Provider</div>
85+
<select class="form-select" id="provider" value={selectedProvider?.provider || null} disabled={disabled} on:change={e => selectProvider(e)}>
86+
<option value={null} disabled selected>{$_('Select Provider')}</option>
87+
{#each providerOptions as op}
88+
<option value={`${op.id}`} selected={op.id === selectedProvider?.provider}>{$_(`${op.name}`)}</option>
89+
{/each}
90+
</select>
91+
</div>
92+
</div>
93+
94+
<div class="instruct-setting-item">
95+
<div class="instruct-setting-dropdown">
96+
<div class="text-primary fw-bold mb-1">Model</div>
97+
<select class="form-select" id="model" value={selectedModel?.id || null} disabled={disabled} on:change={e => selectModel(e)}>
98+
<option value={null} disabled selected>{$_('Select Model')}</option>
99+
{#each modelOptions as op}
100+
<option value={`${op.id}`} selected={op.id === selectedModel?.id}>{$_(`${op.name}`)}</option>
101+
{/each}
102+
</select>
103+
</div>
104+
</div>
105+
</div>
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Please sign in to comment.