diff --git a/src/lib/helpers/types/instructTypes.js b/src/lib/helpers/types/instructTypes.js index 14054cf6..ee8ea9f3 100644 --- a/src/lib/helpers/types/instructTypes.js +++ b/src/lib/helpers/types/instructTypes.js @@ -11,7 +11,32 @@ * @property {string} [instruction] * @property {string} [provider] * @property {string} [model] + * @property {string?} [template] * @property {import('$conversationTypes').ConversationStateModel[]} [states] */ +/** + * @typedef {Object} InstructLogFilter + * @property {number} page - The page number + * @property {number} size - The page size + * @property {string[]?} [agentIds] + * @property {string[]?} [providers] + * @property {string[]?} [models] + * @property {string[]?} [templateNames] + */ + +/** + * @typedef {Object} InstructionLogModel + * @property {string} [id] + * @property {string?} [agent_id] + * @property {string?} [agent_name] + * @property {string} provider + * @property {string} model + * @property {string?} [template_name] + * @property {string} user_message + * @property {string?} [system_instruction] + * @property {string} completion_text + * @property {Date} created_time + */ + export default {}; \ No newline at end of file diff --git a/src/lib/helpers/utils/common.js b/src/lib/helpers/utils/common.js index d3ae5566..823e8821 100644 --- a/src/lib/helpers/utils/common.js +++ b/src/lib/helpers/utils/common.js @@ -67,4 +67,13 @@ export function truncateByPrefix(str, prefix) { } return str.replace(prefix, ''); +} + + +/** + * @param {any[]} arr + * @param {string | number} key + */ +export function removeDuplicates(arr, key) { + return [...new Map(arr.map(item => [item[key], item])).values()]; } \ No newline at end of file diff --git a/src/lib/scss/custom/pages/_instruction.scss b/src/lib/scss/custom/pages/_instruction.scss index 067f6d1f..f80a81a5 100644 --- a/src/lib/scss/custom/pages/_instruction.scss +++ b/src/lib/scss/custom/pages/_instruction.scss @@ -82,4 +82,21 @@ gap: 30px; justify-content: center; } +} + +.instruction-log-col { + max-width: 150px; +} + +.instruction-log-detail-container { + display: flex; + flex-direction: column; + gap: 20px; + padding: 10px 5px; + + .instruction-log-message { + overflow-y: auto; + max-height: 350px; + scrollbar-width: none; + } } \ No newline at end of file diff --git a/src/lib/services/api-endpoints.js b/src/lib/services/api-endpoints.js index ddcf3e20..26cf2212 100644 --- a/src/lib/services/api-endpoints.js +++ b/src/lib/services/api-endpoints.js @@ -45,6 +45,7 @@ export const endpoints = { // agent instruct instructCompletionUrl: `${host}/instruct/{agentId}`, chatCompletionUrl: `${host}/instruct/chat-completion`, + instructLogUrl: `${host}/logger/instruction/log`, // agent realtime interaction agentInitRealtimeSessionUrl: `${host}/agent/{agentId}/realtime/session`, diff --git a/src/lib/services/instruct-service.js b/src/lib/services/instruct-service.js index f9bf8ff3..2b4a4a10 100644 --- a/src/lib/services/instruct-service.js +++ b/src/lib/services/instruct-service.js @@ -22,3 +22,23 @@ export async function sendChatCompletion(request) { const response = await axios.post(url, request); return response.data; } + + +/** + * Get instruction logs + * @param {import('$instructTypes').InstructLogFilter} filter + * @returns {Promise>} + */ +export async function getInstructionLogs(filter) { + const url = endpoints.instructLogUrl; + const response = await axios.get(url, { + params: { + ...filter + }, + paramsSerializer: { + dots: true, + indexes: null, + } + }); + return response.data; +} diff --git a/src/routes/page/instruction/+page.svelte b/src/routes/page/instruction/+page.svelte index 7705c9ff..af0e8011 100644 --- a/src/routes/page/instruction/+page.svelte +++ b/src/routes/page/instruction/+page.svelte @@ -47,6 +47,9 @@ /** @type {string | null} */ let selectedModel = null; + + /** @type {string | null} */ + let selectedTemplate = null; /** @type {import('$agentTypes').AgentModel[]} */ let agents = []; @@ -87,6 +90,7 @@ agentId: selectedAgent?.id, provider: selectedProvider?.provider || DEFAULT_PROVIDER, model: selectedModel || DEFAULT_MODEL, + template: selectedTemplate, states: formattedStates }).then(res => { result = res || ''; @@ -137,6 +141,7 @@ instruction = selectedAgent?.instruction || ''; const template = e.detail.template || null; + selectedTemplate = template?.name || null; if (!!template) { instruction = template?.content || ''; } diff --git a/src/routes/page/instruction/log/+page.svelte b/src/routes/page/instruction/log/+page.svelte new file mode 100644 index 00000000..0410ca33 --- /dev/null +++ b/src/routes/page/instruction/log/+page.svelte @@ -0,0 +1,283 @@ + + + + + + + + + + + +
+
{$_('Log List')}
+
+
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + {#each logItems as item, idx (idx)} + + {/each} + +
{$_('Agent')}{$_('Provider')}{$_('Model')}{$_('Template')}{$_('Created Time')}{$_('')}
+
+ pageTo(pn)} /> +
+
+ +
\ No newline at end of file diff --git a/src/routes/page/instruction/log/log-item.svelte b/src/routes/page/instruction/log/log-item.svelte new file mode 100644 index 00000000..b04a8312 --- /dev/null +++ b/src/routes/page/instruction/log/log-item.svelte @@ -0,0 +1,76 @@ + + + + {item.agent_name || 'N/A'} + {item.provider} + {item.model} + {item.template_name || 'N/A'} + {utcToLocal(item.created_time)} + +
    +
  • + +
  • +
+ + + + +{#if open} + + +
+ {#if !!item.system_instruction} +
+
+ {'System instruction:'} +
+
+ +
+
+ {/if} + {#if !!item.user_message} +
+
+ {'User message:'} +
+
+ +
+
+ {/if} + {#if !!item.completion_text} +
+
+ {'Completion text:'} +
+
+ +
+
+ {/if} +
+ + +{/if} \ No newline at end of file diff --git a/svelte.config.js b/svelte.config.js index 61d9bd45..a5e89ad7 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -53,6 +53,7 @@ const config = { "/page/agent/[agentId]/build", "/page/agent/[agentId]/train", "/page/instruction", + "/page/instruction/log", "/page/conversation", "/page/conversation/[conversationId]", "/page/task",