From 9fbff16a08f4435a07b3c2fbd932df5d41ccc1d6 Mon Sep 17 00:00:00 2001 From: Etienne Perot Date: Sat, 12 Oct 2024 16:14:12 -0700 Subject: [PATCH] feat: add code execution status to chat messages. This adds `code_executions` as an array of code execution statuses to chat messages. The intent of this data is to be displayed in a similar manner as citations: at the bottom of the message, with buttons that open a modal for more info. However, code execution data doesn't fit well in citation modals, because they fundamentally differ in their formatting. Code execution status includes the code that was run (which benefits from being syntax-highlighted), and the output and generated files. This differs from citations which are just list of document names and links. Additionally, code execution is a process, whereas citations are only emitted once. This is why code execution data uses an ID-based approach, where each code execution instance is identified by a unique ID and can be updated by emitting a new `code_execution` message with the same ID. This allows the code execution status to be updated as code runs. --- src/lib/components/chat/Chat.svelte | 26 +++- .../components/chat/Messages/CodeBlock.svelte | 3 +- .../chat/Messages/CodeExecutionModal.svelte | 115 ++++++++++++++++++ .../chat/Messages/CodeExecutions.svelte | 95 +++++++++++++++ .../chat/Messages/ResponseMessage.svelte | 15 +++ 5 files changed, 250 insertions(+), 4 deletions(-) create mode 100644 src/lib/components/chat/Messages/CodeExecutionModal.svelte create mode 100644 src/lib/components/chat/Messages/CodeExecutions.svelte diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 83e3b967f..d84f503da 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -175,10 +175,30 @@ message.statusHistory = [data]; } } else if (type === 'citation') { - if (message?.citations) { - message.citations.push(data); + if (data?.type === 'code_execution') { + // Code execution; update existing code execution by UUID, + // otherwise append. + if (!message?.code_executions) { + message.code_executions = []; + } + let is_update = false; + for (let i = 0; i < message.code_executions.length; i++) { + if (message.code_executions[i].uuid === data.uuid) { + message.code_executions[i] = data; + is_update = true; + break; + } + } + if (!is_update) { + message.code_executions.push(data); + } } else { - message.citations = [data]; + // Regular citation. + if (message?.citations) { + message.citations.push(data); + } else { + message.citations = [data]; + } } } else if (type === 'message') { message.content += data.content; diff --git a/src/lib/components/chat/Messages/CodeBlock.svelte b/src/lib/components/chat/Messages/CodeBlock.svelte index ef17c493a..ca69ce38d 100644 --- a/src/lib/components/chat/Messages/CodeBlock.svelte +++ b/src/lib/components/chat/Messages/CodeBlock.svelte @@ -23,6 +23,7 @@ export let token; export let lang = ''; export let code = ''; + export let allow_execution = true; let _code = ''; $: if (code) { @@ -319,7 +320,7 @@ __builtins__.input = input`); {#if lang.toLowerCase() === 'python' || lang.toLowerCase() === 'py' || (lang === '' && checkPythonCode(code))} {#if executing}
Running
- {:else} + {:else if allow_execution} + + +
+
+
+
+ {$i18n.t('Code')} +
+ + +
+ {#if code_execution?.error} +
+
+
+ {$i18n.t('Error')} +
+ + +
+ {/if} + {#if code_execution?.output} +
+
+
+ {$i18n.t('Output')} +
+ + +
+ {/if} + {#if code_execution?.files && code_execution?.files.length > 0} +
+
+
+ {$i18n.t('Files')} +
+
    + {#each code_execution?.files as file} +
  • + 💾 + {file.name} +
  • + {/each} +
+
+ {/if} +
+
+ + diff --git a/src/lib/components/chat/Messages/CodeExecutions.svelte b/src/lib/components/chat/Messages/CodeExecutions.svelte new file mode 100644 index 000000000..7daa4d926 --- /dev/null +++ b/src/lib/components/chat/Messages/CodeExecutions.svelte @@ -0,0 +1,95 @@ + + + + +{#if _code_executions.length > 0} +
+ {#each _code_executions as code_execution} +
+ +
+ {/each} +
+{/if} + + diff --git a/src/lib/components/chat/Messages/ResponseMessage.svelte b/src/lib/components/chat/Messages/ResponseMessage.svelte index 16193ecc2..4cdff4d7d 100644 --- a/src/lib/components/chat/Messages/ResponseMessage.svelte +++ b/src/lib/components/chat/Messages/ResponseMessage.svelte @@ -35,6 +35,7 @@ import Markdown from './Markdown.svelte'; import Error from './Error.svelte'; import Citations from './Citations.svelte'; + import CodeExecutions from './CodeExecutions.svelte'; import type { Writable } from 'svelte/store'; import type { i18n as i18nType } from 'i18next'; @@ -64,6 +65,17 @@ done: boolean; error?: boolean | { content: string }; citations?: string[]; + code_executions?: { + uuid: string; + name: string; + code: string; + language?: string; + result?: { + error?: string; + output?: string; + files?: { name: string; url: string }[]; + }; + }[]; info?: { openai?: boolean; prompt_tokens?: number; @@ -516,6 +528,9 @@ {#if message.citations} {/if} + {#if message.code_executions} + + {/if} {/if}