paufinement de l'UI du chat

This commit is contained in:
fabien committed 2026-10-04 21:55:31 +02:00
1 parent 0a6ffab050
commit 87eeb41364
6 files changed
+93 -13

No files matched your search

+1
View File
@@ -2,6 +2,7 @@ package llm
import ( import (
"context" "context"
"fmt" "fmt"
"log/slog" "log/slog"
+5 -1
View File
@@ -2,11 +2,15 @@ package chat
import ( import (
"context" "context"
_ "embed"
"sync" "sync"
"trankilou.fr/lassistanoque/backend/internal/domain" "trankilou.fr/lassistanoque/backend/internal/domain"
) )
//go:embed system_prompt.md
var systemSystemPrompt string
type ChatSession struct { type ChatSession struct {
userID string userID string
teamID string teamID string
@@ -43,7 +47,7 @@ func (s *ChatSession) run(ctx context.Context) error {
systemPrompt := &domain.Message{ systemPrompt := &domain.Message{
Role: string(domain.RoleSystem), Role: string(domain.RoleSystem),
Content: s.agent.SystemPrompt, Content: systemSystemPrompt + "\n\n## Customization\n\n" + s.agent.SystemPrompt,
} }
continue_loop := true continue_loop := true
@@ -0,0 +1,27 @@
You are an assistant that helps users by relying on the tools and skills made available to you. Reply in the user's language.
## Style: be direct
Answer precisely and concisely. Start with the answer, with no preamble, no restating of the question, and no summarizing conclusion.
Match the length to the actual need: a simple question calls for a short answer, a complex one may justify more development. Don't digress and don't add information the user didn't ask for, unless it is essential to keep them from making a mistake. If the answer fits in one sentence, one sentence is enough.
Conciseness applies to style, never at the expense of the completeness the user asked for.
## Reliability: never invent anything
Only state what you know for certain or have verified. If you have any doubt about a fact, figure, name, date, or the current state of a system, check the tools before answering: they are your source of truth, your memory is not.
If the tools cannot confirm a piece of information, say so clearly ("I couldn't verify this", "the tools returned no results") rather than filling the gap with a guess. Always distinguish what is established by a source from what is your own inference, and flag it when it is the latter. Saying "I don't know" is always better than giving an invented answer.
## Perseverance: see it through
When the user asks for a complete or exhaustive list, or for any task whose result must be whole, don't settle for a first, partial result. Check whether results are paginated or truncated, rerun the tools with other parameters, pages, or queries, and cross-check sources until you have covered the requested scope.
Never present a partial result as complete. If, despite your efforts, you cannot guarantee completeness (tool limitation, inaccessible source), state precisely what is missing or could not be verified. If a tool fails or returns an unusable result, try another approach before concluding.
## Tools and skills
Use the available tools and skills whenever they can help you answer more accurately, verify a fact, or complete the task. Don't answer from memory when a tool can provide the answer. If several tools are relevant, combine them. When a task matches an available skill, consult it before starting.
You may skip them for purely conversational exchanges or questions whose answer depends on no information that needs verifying.
Binary file not shown.
@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import {autofocus} from "$lib/ui/autofocus" import {autofocus} from "$lib/ui/autofocus"
import { onMount } from "svelte" import {onMount, tick } from "svelte"
import {page} from "$app/state" import {page} from "$app/state"
import {chatApi} from "$lib/api/endpoints/chat" import {chatApi} from "$lib/api/endpoints/chat"
import type { PageProps } from './$types'; import type { PageProps } from './$types';
@@ -20,9 +20,12 @@
let chatWithMessage : ChatWithMessages = await chatApi.getChat(data.spaceId, data.chatId) let chatWithMessage : ChatWithMessages = await chatApi.getChat(data.spaceId, data.chatId)
messages = chatWithMessage.messages messages = chatWithMessage.messages
} }
await tick()
historyDiv.scrollTop = historyDiv.scrollHeight;
}) })
let historyDiv: HTMLDivElement; let historyDiv: HTMLDivElement;
let inputPrompt: HTMLDivElement;
const sendRequest = async(theprompt:string) => { const sendRequest = async(theprompt:string) => {
prompt = "" prompt = ""
@@ -34,6 +37,12 @@
if (waiting && chunk.role==="assistant") { if (waiting && chunk.role==="assistant") {
waiting = false waiting = false
} }
if (chunk.done) {
document
.querySelectorAll<HTMLDivElement>('div.reasoning:not(.hidden)')
.forEach((el) => el.classList.add('hidden'));
return
}
if (chunk.role!=lastrole || chunk.toolName!=lastToolName) { if (chunk.role!=lastrole || chunk.toolName!=lastToolName) {
const currentDate = new Date() const currentDate = new Date()
@@ -80,7 +89,9 @@
} }
const handleOnSubmit = async ()=>{ const handleOnSubmit = async ()=>{
historyDiv.scrollTop = historyDiv.scrollHeight;
await sendRequest(prompt) await sendRequest(prompt)
inputPrompt.focus()
} }
</script> </script>
@@ -94,7 +105,7 @@
</div> </div>
{/if} {/if}
{#if message.toolcalls != null && message.toolcalls.length>0} {#if message.toolcalls != null && message.toolcalls.length>0}
<div class="text-green-600">⚒️ Appel de l'outil {message.toolcalls[0].Function.Name}</div> <div class="tool text-sm mt-2 py-1 px-2 rounded">⚒️ Appel de l'outil {message.toolcalls[0].Function.Name}</div>
{:else} {:else}
<div class="message-content"> <div class="message-content">
<SvelteMarkdown source={message.content} streaming={true}/> <SvelteMarkdown source={message.content} streaming={true}/>
@@ -114,6 +125,7 @@
placeholder="..." placeholder="..."
bind:value={prompt} bind:value={prompt}
use:autofocus use:autofocus
bind:this={inputPrompt}
/> />
<button class="chatbutton">Go</button> <button class="chatbutton">Go</button>
</form> </form>
+46 -10
View File
@@ -275,10 +275,54 @@ h2 {
/* chat */ /* chat */
.message { .message {
@apply rounded p-2; /*@apply rounded p-2;*/
&.user { &.user {
@apply bg-sky-700 dark:text-white; @apply bg-sky-500/20 px-2 py-1 text-sky-700 dark:text-sky-300;
}
.tool {
@apply bg-green-500/20 px-2 py-1 text-green-700 dark:text-green-300;
}
hr {
@apply my-4;
}
ul,
ol {
@apply my-2;
}
h1 {
@apply text-2xl font-bold;
}
h2 {
@apply text-xl font-bold;
}
h3 {
@apply text-lg font-bold;
}
h4 {
@apply text-base;
}
h5 {
@apply text-sm;
}
li {
@apply ml-5 list-disc pl-4 marker:text-xl;
}
pre {
@apply my-2 rounded p-1 whitespace-pre dark:bg-stone-700;
}
p {
@apply my-2;
} }
} }
@@ -289,11 +333,3 @@ h2 {
@apply text-white/50; @apply text-white/50;
} }
} }
.message-content p {
@apply my-2;
}
.message-content pre {
@apply my-2 whitespace-pre dark:bg-stone-700;
}