Spaces:
Paused
Paused
Huggingface IT
commited on
Commit
·
181d9ef
1
Parent(s):
97802e3
add energy time estimate
Browse files- Dockerfile.dev +15 -0
- compose.dev.yml +22 -0
- src/lib/components/chat/ChatMessage.svelte +20 -0
- src/lib/server/textGeneration/generate.ts +19 -0
- src/lib/types/Message.ts +3 -0
- src/lib/types/MessageUpdate.ts +9 -1
- src/routes/conversation/[id]/+server.ts +8 -0
Dockerfile.dev
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM node:20-slim
|
| 2 |
+
|
| 3 |
+
USER root
|
| 4 |
+
RUN apt-get update && apt-get install -y \
|
| 5 |
+
python3 make g++ curl gnupg && apt-get clean
|
| 6 |
+
|
| 7 |
+
RUN mkdir -p /home/user/.cache && chown -R 1000:1000 /home/user/.cache
|
| 8 |
+
|
| 9 |
+
#USER user
|
| 10 |
+
WORKDIR /app
|
| 11 |
+
|
| 12 |
+
EXPOSE 5173
|
| 13 |
+
|
| 14 |
+
# start bash
|
| 15 |
+
CMD ["bash"]
|
compose.dev.yml
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
services:
|
| 2 |
+
app:
|
| 3 |
+
build:
|
| 4 |
+
context: .
|
| 5 |
+
dockerfile: Dockerfile.dev
|
| 6 |
+
ports:
|
| 7 |
+
- "5173:5173" # adapt if using another dev server port
|
| 8 |
+
volumes:
|
| 9 |
+
- .:/app
|
| 10 |
+
- /app/node_modules # pour éviter les conflits entre host et conteneur
|
| 11 |
+
working_dir: /app
|
| 12 |
+
user: "1000:1000"
|
| 13 |
+
tty: true
|
| 14 |
+
mongo:
|
| 15 |
+
image: mongo:7
|
| 16 |
+
ports:
|
| 17 |
+
- "27017:27017"
|
| 18 |
+
volumes:
|
| 19 |
+
- mongo-data:/data/db
|
| 20 |
+
|
| 21 |
+
volumes:
|
| 22 |
+
mongo-data:
|
src/lib/components/chat/ChatMessage.svelte
CHANGED
|
@@ -150,6 +150,7 @@
|
|
| 150 |
class="mt-5 h-3 w-3 flex-none select-none rounded-full shadow-lg"
|
| 151 |
/>
|
| 152 |
{/if}
|
|
|
|
| 153 |
<div
|
| 154 |
class="relative min-h-[calc(2rem+theme(spacing[3.5])*2)] min-w-[60px] break-words rounded-2xl border border-gray-100 bg-gradient-to-br from-gray-50 px-5 py-3.5 text-gray-600 prose-pre:my-2 dark:border-gray-800 dark:from-gray-800/40 dark:text-gray-300"
|
| 155 |
>
|
|
@@ -197,6 +198,25 @@
|
|
| 197 |
class="prose max-w-none dark:prose-invert max-sm:prose-sm prose-headings:font-semibold prose-h1:text-lg prose-h2:text-base prose-h3:text-base prose-pre:bg-gray-800 dark:prose-pre:bg-gray-900"
|
| 198 |
>
|
| 199 |
<MarkdownRenderer content={message.content} sources={webSearchSources} />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 200 |
</div>
|
| 201 |
</div>
|
| 202 |
|
|
|
|
| 150 |
class="mt-5 h-3 w-3 flex-none select-none rounded-full shadow-lg"
|
| 151 |
/>
|
| 152 |
{/if}
|
| 153 |
+
|
| 154 |
<div
|
| 155 |
class="relative min-h-[calc(2rem+theme(spacing[3.5])*2)] min-w-[60px] break-words rounded-2xl border border-gray-100 bg-gradient-to-br from-gray-50 px-5 py-3.5 text-gray-600 prose-pre:my-2 dark:border-gray-800 dark:from-gray-800/40 dark:text-gray-300"
|
| 156 |
>
|
|
|
|
| 198 |
class="prose max-w-none dark:prose-invert max-sm:prose-sm prose-headings:font-semibold prose-h1:text-lg prose-h2:text-base prose-h3:text-base prose-pre:bg-gray-800 dark:prose-pre:bg-gray-900"
|
| 199 |
>
|
| 200 |
<MarkdownRenderer content={message.content} sources={webSearchSources} />
|
| 201 |
+
{#if message.metadata?.energy_wh || message.metadata?.duration_seconds}
|
| 202 |
+
<div class="mt-2 flex gap-2">
|
| 203 |
+
{#if message.metadata?.energy_wh}
|
| 204 |
+
<div
|
| 205 |
+
class="text-xs text-gray-400 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded w-fit"
|
| 206 |
+
>
|
| 207 |
+
◊ {message.metadata.energy_wh} Wh
|
| 208 |
+
</div>
|
| 209 |
+
{/if}
|
| 210 |
+
{#if message.metadata?.duration_seconds}
|
| 211 |
+
<div
|
| 212 |
+
class="text-xs text-gray-400 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded w-fit"
|
| 213 |
+
>
|
| 214 |
+
{message.metadata.duration_seconds} sec
|
| 215 |
+
</div>
|
| 216 |
+
{/if}
|
| 217 |
+
</div>
|
| 218 |
+
{/if}
|
| 219 |
+
|
| 220 |
</div>
|
| 221 |
</div>
|
| 222 |
|
src/lib/server/textGeneration/generate.ts
CHANGED
|
@@ -127,6 +127,25 @@ Do not use prefixes such as Response: or Answer: when answering to the user.`,
|
|
| 127 |
interrupted,
|
| 128 |
webSources: output.webSources,
|
| 129 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
continue;
|
| 131 |
}
|
| 132 |
|
|
|
|
| 127 |
interrupted,
|
| 128 |
webSources: output.webSources,
|
| 129 |
};
|
| 130 |
+
|
| 131 |
+
// simulation of metadata
|
| 132 |
+
const durationInSeconds = (new Date().getTime() - startTime.getTime()) / 1000;
|
| 133 |
+
const energyUsedwh = +(50 * (durationInSeconds / 3600)).toFixed(6); // 50W is a guess
|
| 134 |
+
|
| 135 |
+
yield {
|
| 136 |
+
type: MessageUpdateType.Metadata,
|
| 137 |
+
key: "energy_wh",
|
| 138 |
+
value: energyUsedwh,
|
| 139 |
+
};
|
| 140 |
+
yield {
|
| 141 |
+
type: MessageUpdateType.Metadata,
|
| 142 |
+
key: "duration_seconds",
|
| 143 |
+
value: durationInSeconds,
|
| 144 |
+
};
|
| 145 |
+
|
| 146 |
+
console.log('model', model);
|
| 147 |
+
console.log('output', output);
|
| 148 |
+
|
| 149 |
continue;
|
| 150 |
}
|
| 151 |
|
src/lib/types/Message.ts
CHANGED
|
@@ -25,6 +25,9 @@ export type Message = Partial<Timestamps> & {
|
|
| 25 |
|
| 26 |
// goes one level deep
|
| 27 |
children?: Message["id"][];
|
|
|
|
|
|
|
|
|
|
| 28 |
};
|
| 29 |
|
| 30 |
export type MessageFile = {
|
|
|
|
| 25 |
|
| 26 |
// goes one level deep
|
| 27 |
children?: Message["id"][];
|
| 28 |
+
|
| 29 |
+
// metadata
|
| 30 |
+
metadata?: Record<string, string | number>;
|
| 31 |
};
|
| 32 |
|
| 33 |
export type MessageFile = {
|
src/lib/types/MessageUpdate.ts
CHANGED
|
@@ -9,7 +9,8 @@ export type MessageUpdate =
|
|
| 9 |
| MessageStreamUpdate
|
| 10 |
| MessageFileUpdate
|
| 11 |
| MessageFinalAnswerUpdate
|
| 12 |
-
| MessageReasoningUpdate
|
|
|
|
| 13 |
|
| 14 |
export enum MessageUpdateType {
|
| 15 |
Status = "status",
|
|
@@ -20,6 +21,7 @@ export enum MessageUpdateType {
|
|
| 20 |
File = "file",
|
| 21 |
FinalAnswer = "finalAnswer",
|
| 22 |
Reasoning = "reasoning",
|
|
|
|
| 23 |
}
|
| 24 |
|
| 25 |
// Status
|
|
@@ -147,3 +149,9 @@ export interface MessageFinalAnswerUpdate {
|
|
| 147 |
interrupted: boolean;
|
| 148 |
webSources?: { uri: string; title: string }[];
|
| 149 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
| MessageStreamUpdate
|
| 10 |
| MessageFileUpdate
|
| 11 |
| MessageFinalAnswerUpdate
|
| 12 |
+
| MessageReasoningUpdate
|
| 13 |
+
| MessageMetadataUpdate;
|
| 14 |
|
| 15 |
export enum MessageUpdateType {
|
| 16 |
Status = "status",
|
|
|
|
| 21 |
File = "file",
|
| 22 |
FinalAnswer = "finalAnswer",
|
| 23 |
Reasoning = "reasoning",
|
| 24 |
+
Metadata = "metadata",
|
| 25 |
}
|
| 26 |
|
| 27 |
// Status
|
|
|
|
| 149 |
interrupted: boolean;
|
| 150 |
webSources?: { uri: string; title: string }[];
|
| 151 |
}
|
| 152 |
+
|
| 153 |
+
export interface MessageMetadataUpdate {
|
| 154 |
+
type: MessageUpdateType.Metadata;
|
| 155 |
+
key: string;
|
| 156 |
+
value: string | number;
|
| 157 |
+
}
|
src/routes/conversation/[id]/+server.ts
CHANGED
|
@@ -402,6 +402,12 @@ export async function POST({ request, locals, params, getClientAddress }) {
|
|
| 402 |
];
|
| 403 |
}
|
| 404 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 405 |
// Append to the persistent message updates if it's not a stream update
|
| 406 |
if (
|
| 407 |
event.type !== MessageUpdateType.Stream &&
|
|
@@ -417,6 +423,8 @@ export async function POST({ request, locals, params, getClientAddress }) {
|
|
| 417 |
messageToWriteTo?.updates?.push(event);
|
| 418 |
}
|
| 419 |
|
|
|
|
|
|
|
| 420 |
// Avoid remote keylogging attack executed by watching packet lengths
|
| 421 |
// by padding the text with null chars to a fixed length
|
| 422 |
// https://cdn.arstechnica.net/wp-content/uploads/2024/03/LLM-Side-Channel.pdf
|
|
|
|
| 402 |
];
|
| 403 |
}
|
| 404 |
|
| 405 |
+
// Add metadata
|
| 406 |
+
else if (event.type === MessageUpdateType.Metadata) {
|
| 407 |
+
messageToWriteTo.metadata ??= {};
|
| 408 |
+
messageToWriteTo.metadata[event.key] = event.value;
|
| 409 |
+
}
|
| 410 |
+
|
| 411 |
// Append to the persistent message updates if it's not a stream update
|
| 412 |
if (
|
| 413 |
event.type !== MessageUpdateType.Stream &&
|
|
|
|
| 423 |
messageToWriteTo?.updates?.push(event);
|
| 424 |
}
|
| 425 |
|
| 426 |
+
|
| 427 |
+
|
| 428 |
// Avoid remote keylogging attack executed by watching packet lengths
|
| 429 |
// by padding the text with null chars to a fixed length
|
| 430 |
// https://cdn.arstechnica.net/wp-content/uploads/2024/03/LLM-Side-Channel.pdf
|