|
3 | 3 | import { fly } from 'svelte/transition'; |
4 | 4 | import { _ } from 'svelte-i18n'; |
5 | 5 | import util from "lodash"; |
6 | | - import { Button, Col, Row } from '@sveltestrap/sveltestrap'; |
| 6 | + import { Button, Card, CardBody, Col, Row } from '@sveltestrap/sveltestrap'; |
7 | 7 | import LoadingDots from '$lib/common/LoadingDots.svelte'; |
8 | 8 | import HeadTitle from '$lib/common/HeadTitle.svelte'; |
9 | 9 | import Breadcrumb from '$lib/common/Breadcrumb.svelte'; |
10 | 10 | import Markdown from '$lib/common/markdown/Markdown.svelte'; |
11 | | - import InstructionSetting from './instruction-components/instruction-setting.svelte'; |
12 | 11 | import InstructionState from './instruction-components/instruction-state.svelte'; |
13 | 12 | import { getAgents } from '$lib/services/agent-service'; |
14 | 13 | import LoadingToComplete from '$lib/common/LoadingToComplete.svelte'; |
15 | 14 | import { sendChatCompletion } from '$lib/services/instruct-service'; |
16 | 15 | import { getLlmConfigs } from '$lib/services/llm-provider-service'; |
17 | 16 | 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'; |
18 | 21 |
|
19 | 22 | const maxLength = 64000; |
20 | 23 | const DEFAULT_PROVIDER = 'openai'; |
21 | 24 | const DEFAULT_MODEL = 'gpt-4o-mini'; |
22 | 25 |
|
| 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 | +
|
23 | 33 | let isLoading = false; |
24 | 34 | let isThinking = false; |
25 | 35 | let requestDone = false; |
|
32 | 42 | /** @type {import('$agentTypes').AgentModel | null} */ |
33 | 43 | let selectedAgent = null; |
34 | 44 |
|
35 | | - /** @type {string | null} */ |
| 45 | + /** @type {import('$commonTypes').LlmConfig?} */ |
36 | 46 | let selectedProvider = null; |
37 | 47 |
|
38 | 48 | /** @type {string | null} */ |
|
49 | 59 | { key: '', value: ''} |
50 | 60 | ]; |
51 | 61 |
|
| 62 | + /** @type {string}*/ |
| 63 | + let selectedTab = tabs[0].name; |
| 64 | +
|
52 | 65 | onMount(async () => { |
53 | 66 | try { |
54 | 67 | isLoading = true; |
|
62 | 75 | } |
63 | 76 | }); |
64 | 77 |
|
65 | | -
|
66 | 78 | function sendRequest() { |
67 | 79 | isThinking = true; |
68 | 80 | requestDone = false; |
|
73 | 85 | text: util.trim(text) || '', |
74 | 86 | instruction: util.trim(instruction) || null, |
75 | 87 | agentId: selectedAgent?.id, |
76 | | - provider: selectedProvider || DEFAULT_PROVIDER, |
| 88 | + provider: selectedProvider?.provider || DEFAULT_PROVIDER, |
77 | 89 | model: selectedModel || DEFAULT_MODEL, |
78 | 90 | states: formattedStates |
79 | 91 | }).then(res => { |
|
121 | 133 |
|
122 | 134 | /** @param {any} e */ |
123 | 135 | function onAgentSelected(e) { |
124 | | - selectedAgent = e.detail.selectedAgent || null; |
| 136 | + selectedAgent = e.detail.agent || null; |
125 | 137 | instruction = selectedAgent?.instruction || ''; |
126 | 138 |
|
127 | | - const template = e.detail.selectedTemplate || null; |
| 139 | + const template = e.detail.template || null; |
128 | 140 | if (!!template) { |
129 | 141 | instruction = template?.content || ''; |
130 | 142 | } |
131 | 143 |
|
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; |
133 | 148 | } |
134 | 149 | |
135 | 150 | /** @param {any} e */ |
136 | 151 | 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; |
139 | 159 | } |
140 | 160 | </script> |
141 | 161 |
|
|
151 | 171 | rows={8} |
152 | 172 | maxlength={maxLength} |
153 | 173 | disabled={isThinking} |
154 | | - placeholder={'Start typing here...'} |
| 174 | + placeholder={'Enter input message...'} |
155 | 175 | bind:value={text} |
156 | 176 | on:keydown={(e) => pressKey(e)} |
157 | 177 | /> |
|
207 | 227 | </div> |
208 | 228 | </div> |
209 | 229 |
|
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 | | -
|
224 | 230 | <div class="d-xl-flex mt-4 mb-5"> |
225 | 231 | <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> |
226 | 253 | <Row class="instruct-setting-container"> |
227 | | - <Col lg="9"> |
| 254 | + <Col lg="7"> |
228 | 255 | <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;"> |
246 | 257 | <textarea |
247 | 258 | class='form-control knowledge-textarea' |
248 | 259 | rows={19} |
249 | 260 | maxlength={maxLength} |
250 | 261 | disabled={isThinking} |
251 | | - placeholder={'Start typing here...'} |
| 262 | + placeholder={'Enter instruction...'} |
252 | 263 | bind:value={instruction} |
253 | 264 | /> |
| 265 | + <div class="text-secondary text-end text-count"> |
| 266 | + <div>{instruction?.length || 0}/{maxLength}</div> |
| 267 | + </div> |
254 | 268 | </div> |
255 | 269 | </div> |
256 | 270 | </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 | + |
259 | 319 | </Col> |
260 | 320 | </Row> |
261 | 321 | </div> |
|
0 commit comments