victor HF Staff commited on
Commit
dd75b82
·
1 Parent(s): 6115da3

Remove reasoning

Browse files
.env CHANGED
@@ -36,8 +36,6 @@ AUTOMATIC_LOGIN=
36
  ### Local Storage ###
37
  MONGO_STORAGE_PATH= # where is the db folder stored
38
 
39
- REASONING_SUMMARY=false # Change this to false to disable reasoning summary
40
-
41
  ## Models overrides
42
  MODELS=
43
 
 
36
  ### Local Storage ###
37
  MONGO_STORAGE_PATH= # where is the db folder stored
38
 
 
 
39
  ## Models overrides
40
  MODELS=
41
 
scripts/populate.ts CHANGED
@@ -22,8 +22,6 @@ import { generateSearchTokens } from "../src/lib/utils/searchTokens.ts";
22
  import { ReviewStatus } from "../src/lib/types/Review.ts";
23
  import fs from "fs";
24
  import path from "path";
25
- import { MessageUpdateType } from "../src/lib/types/MessageUpdate.ts";
26
- import { MessageReasoningUpdateType } from "../src/lib/types/MessageUpdate.ts";
27
 
28
  const rl = readline.createInterface({
29
  input: process.stdin,
@@ -62,7 +60,6 @@ async function generateMessages(preprompt?: string): Promise<Message[]> {
62
  const convLength = faker.number.int({ min: 1, max: 25 }) * 2; // must always be even
63
 
64
  for (let i = 0; i < convLength; i++) {
65
- const hasReasoning = Math.random() < 0.2;
66
  lastId = addChildren(
67
  {
68
  messages,
@@ -80,17 +77,6 @@ async function generateMessages(preprompt?: string): Promise<Message[]> {
80
  : ""),
81
  createdAt: faker.date.recent({ days: 30 }),
82
  updatedAt: faker.date.recent({ days: 30 }),
83
- reasoning: hasReasoning ? faker.lorem.paragraphs(2) : undefined,
84
- updates: hasReasoning
85
- ? [
86
- {
87
- type: MessageUpdateType.Reasoning,
88
- subtype: MessageReasoningUpdateType.Status,
89
- uuid: crypto.randomUUID(),
90
- status: "thinking",
91
- },
92
- ]
93
- : [],
94
  interrupted: !isUser && i === convLength - 1 && isInterrupted,
95
  },
96
  lastId
@@ -101,7 +87,6 @@ async function generateMessages(preprompt?: string): Promise<Message[]> {
101
  const convLength = faker.number.int({ min: 2, max: 200 });
102
 
103
  for (let i = 0; i < convLength; i++) {
104
- const hasReasoning = Math.random() < 0.2;
105
  addChildren(
106
  {
107
  messages,
@@ -117,17 +102,6 @@ async function generateMessages(preprompt?: string): Promise<Message[]> {
117
  (!isUser && Math.random() < 0.1
118
  ? "\n```\n" + faker.helpers.arrayElement(samples) + "\n```\n"
119
  : ""),
120
- reasoning: hasReasoning ? faker.lorem.paragraphs(2) : undefined,
121
- updates: hasReasoning
122
- ? [
123
- {
124
- type: MessageUpdateType.Reasoning,
125
- subtype: MessageReasoningUpdateType.Status,
126
- uuid: crypto.randomUUID(),
127
- status: "thinking",
128
- },
129
- ]
130
- : [],
131
  createdAt: faker.date.recent({ days: 30 }),
132
  updatedAt: faker.date.recent({ days: 30 }),
133
  interrupted: !isUser && i === convLength - 1 && isInterrupted,
 
22
  import { ReviewStatus } from "../src/lib/types/Review.ts";
23
  import fs from "fs";
24
  import path from "path";
 
 
25
 
26
  const rl = readline.createInterface({
27
  input: process.stdin,
 
60
  const convLength = faker.number.int({ min: 1, max: 25 }) * 2; // must always be even
61
 
62
  for (let i = 0; i < convLength; i++) {
 
63
  lastId = addChildren(
64
  {
65
  messages,
 
77
  : ""),
78
  createdAt: faker.date.recent({ days: 30 }),
79
  updatedAt: faker.date.recent({ days: 30 }),
 
 
 
 
 
 
 
 
 
 
 
80
  interrupted: !isUser && i === convLength - 1 && isInterrupted,
81
  },
82
  lastId
 
87
  const convLength = faker.number.int({ min: 2, max: 200 });
88
 
89
  for (let i = 0; i < convLength; i++) {
 
90
  addChildren(
91
  {
92
  messages,
 
102
  (!isUser && Math.random() < 0.1
103
  ? "\n```\n" + faker.helpers.arrayElement(samples) + "\n```\n"
104
  : ""),
 
 
 
 
 
 
 
 
 
 
 
105
  createdAt: faker.date.recent({ days: 30 }),
106
  updatedAt: faker.date.recent({ days: 30 }),
107
  interrupted: !isUser && i === convLength - 1 && isInterrupted,
src/lib/components/NavMenu.svelte CHANGED
@@ -192,7 +192,7 @@
192
 
193
  <span class="flex gap-1">
194
  <a
195
- href="{base}/settings"
196
  class="flex h-9 flex-none flex-grow items-center gap-1.5 rounded-lg pl-2.5 pr-2 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700"
197
  >
198
  Settings
 
192
 
193
  <span class="flex gap-1">
194
  <a
195
+ href="{base}/settings/application"
196
  class="flex h-9 flex-none flex-grow items-center gap-1.5 rounded-lg pl-2.5 pr-2 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700"
197
  >
198
  Settings
src/lib/components/chat/ChatMessage.svelte CHANGED
@@ -12,11 +12,7 @@
12
  import CarbonPen from "~icons/carbon/pen";
13
  import UploadedFile from "./UploadedFile.svelte";
14
 
15
- import {
16
- MessageUpdateType,
17
- type MessageReasoningUpdate,
18
- MessageReasoningUpdateType,
19
- } from "$lib/types/MessageUpdate";
20
  import MarkdownRenderer from "./MarkdownRenderer.svelte";
21
  import OpenReasoningResults from "./OpenReasoningResults.svelte";
22
  import Alternatives from "./Alternatives.svelte";
@@ -71,29 +67,9 @@
71
  let editContentEl: HTMLTextAreaElement | undefined = $state();
72
  let editFormEl: HTMLFormElement | undefined = $state();
73
 
74
- let reasoningUpdates = $derived(
75
- (message.updates?.filter(({ type }) => type === MessageUpdateType.Reasoning) ??
76
- []) as MessageReasoningUpdate[]
77
- );
78
-
79
- // const messageFinalAnswer = $derived(
80
- // message.updates?.find(
81
- // ({ type }) => type === MessageUpdateType.FinalAnswer
82
- // ) as MessageFinalAnswerUpdate
83
- // );
84
- // const urlNotTrailing = $derived(page.url.pathname.replace(/\/$/, ""));
85
- // let downloadLink = $derived(urlNotTrailing + `/message/${message.id}/prompt`);
86
-
87
  // Zero-config reasoning autodetection: detect <think> blocks in content
88
  const THINK_BLOCK_REGEX = /(<think>[\s\S]*?(?:<\/think>|$))/g;
89
- let thinkSegments = $derived.by(() => message.content.split(THINK_BLOCK_REGEX));
90
- let hasServerReasoning = $derived(
91
- reasoningUpdates &&
92
- reasoningUpdates.length > 0 &&
93
- !!message.reasoning &&
94
- message.reasoning.trim().length > 0
95
- );
96
- let hasClientThink = $derived(!hasServerReasoning && thinkSegments.length > 1);
97
 
98
  $effect(() => {
99
  if (isCopied) {
@@ -143,18 +119,6 @@
143
  </div>
144
  {/if}
145
 
146
- {#if hasServerReasoning}
147
- {@const summaries = reasoningUpdates
148
- .filter((u) => u.subtype === MessageReasoningUpdateType.Status)
149
- .map((u) => u.status)}
150
-
151
- <OpenReasoningResults
152
- summary={summaries[summaries.length - 1] || ""}
153
- content={message.reasoning || ""}
154
- loading={loading && message.content.length === 0}
155
- />
156
- {/if}
157
-
158
  <div bind:this={contentEl}>
159
  {#if isLast && loading && message.content.length === 0}
160
  <IconLoading classNames="loading inline ml-2 first:ml-0" />
 
12
  import CarbonPen from "~icons/carbon/pen";
13
  import UploadedFile from "./UploadedFile.svelte";
14
 
15
+ import { MessageUpdateType } from "$lib/types/MessageUpdate";
 
 
 
 
16
  import MarkdownRenderer from "./MarkdownRenderer.svelte";
17
  import OpenReasoningResults from "./OpenReasoningResults.svelte";
18
  import Alternatives from "./Alternatives.svelte";
 
67
  let editContentEl: HTMLTextAreaElement | undefined = $state();
68
  let editFormEl: HTMLFormElement | undefined = $state();
69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  // Zero-config reasoning autodetection: detect <think> blocks in content
71
  const THINK_BLOCK_REGEX = /(<think>[\s\S]*?(?:<\/think>|$))/g;
72
+ let hasClientThink = $derived(message.content.split(THINK_BLOCK_REGEX).length > 1);
 
 
 
 
 
 
 
73
 
74
  $effect(() => {
75
  if (isCopied) {
 
119
  </div>
120
  {/if}
121
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  <div bind:this={contentEl}>
123
  {#if isLast && loading && message.content.length === 0}
124
  <IconLoading classNames="loading inline ml-2 first:ml-0" />
src/lib/constants/routerExamples.ts CHANGED
@@ -55,8 +55,7 @@ export const routerExamples: RouterExample[] = [
55
  followUps: [
56
  {
57
  title: "Dark mode",
58
- prompt:
59
- "Extend the Tailwind CSS landing page with a toggleable dark mode that remembers the user's choice.",
60
  },
61
  {
62
  title: "Add blog teasers",
 
55
  followUps: [
56
  {
57
  title: "Dark mode",
58
+ prompt: "Add dark mode and make it the default",
 
59
  },
60
  {
61
  title: "Add blog teasers",
src/lib/server/api/routes/groups/models.ts CHANGED
@@ -13,7 +13,6 @@ export type GETModelsResponse = Array<{
13
  datasetUrl?: string;
14
  displayName: string;
15
  description?: string;
16
- reasoning: boolean;
17
  logoUrl?: string;
18
  providers?: Array<{ provider: string } & Record<string, unknown>>;
19
  promptExamples?: { title: string; prompt: string }[];
@@ -50,7 +49,6 @@ export const modelGroup = new Elysia().group("/models", (app) =>
50
  datasetUrl: model.datasetUrl,
51
  displayName: model.displayName,
52
  description: model.description,
53
- reasoning: !!model.reasoning,
54
  logoUrl: model.logoUrl,
55
  providers: model.providers as unknown as Array<
56
  { provider: string } & Record<string, unknown>
 
13
  datasetUrl?: string;
14
  displayName: string;
15
  description?: string;
 
16
  logoUrl?: string;
17
  providers?: Array<{ provider: string } & Record<string, unknown>>;
18
  promptExamples?: { title: string; prompt: string }[];
 
49
  datasetUrl: model.datasetUrl,
50
  displayName: model.displayName,
51
  description: model.description,
 
52
  logoUrl: model.logoUrl,
53
  providers: model.providers as unknown as Array<
54
  { provider: string } & Record<string, unknown>
src/lib/server/models.ts CHANGED
@@ -15,21 +15,6 @@ const sanitizeJSONEnv = (val: string, fallback: string) => {
15
  return unquoted || fallback;
16
  };
17
 
18
- const reasoningSchema = z.union([
19
- z.object({
20
- type: z.literal("regex"), // everything is reasoning, extract the answer from the regex
21
- regex: z.string(),
22
- }),
23
- z.object({
24
- type: z.literal("tokens"), // use beginning and end tokens that define the reasoning portion of the answer
25
- beginToken: z.string(), // empty string means the model starts in reasoning mode
26
- endToken: z.string(),
27
- }),
28
- z.object({
29
- type: z.literal("summarize"), // everything is reasoning, summarize the answer
30
- }),
31
- ]);
32
-
33
  const modelConfig = z.object({
34
  /** Used as an identifier in DB */
35
  id: z.string().optional(),
@@ -75,7 +60,6 @@ const modelConfig = z.object({
75
  embeddingModel: z.never().optional(),
76
  /** Used to enable/disable system prompt usage */
77
  systemRoleSupported: z.boolean().default(true),
78
- reasoning: reasoningSchema.optional(),
79
  });
80
 
81
  type ModelConfig = z.infer<typeof modelConfig>;
 
15
  return unquoted || fallback;
16
  };
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  const modelConfig = z.object({
19
  /** Used as an identifier in DB */
20
  id: z.string().optional(),
 
60
  embeddingModel: z.never().optional(),
61
  /** Used to enable/disable system prompt usage */
62
  systemRoleSupported: z.boolean().default(true),
 
63
  });
64
 
65
  type ModelConfig = z.infer<typeof modelConfig>;
src/lib/server/router/endpoint.ts CHANGED
@@ -86,12 +86,10 @@ function stripReasoningBlocks(text: string): string {
86
  }
87
 
88
  function stripReasoningFromMessage(message: EndpointMessage): EndpointMessage {
89
- const { reasoning: _reasoning, ...rest } = message;
90
- void _reasoning;
91
  const content =
92
  typeof message.content === "string" ? stripReasoningBlocks(message.content) : message.content;
93
  return {
94
- ...rest,
95
  content,
96
  };
97
  }
 
86
  }
87
 
88
  function stripReasoningFromMessage(message: EndpointMessage): EndpointMessage {
 
 
89
  const content =
90
  typeof message.content === "string" ? stripReasoningBlocks(message.content) : message.content;
91
  return {
92
+ ...message,
93
  content,
94
  };
95
  }
src/lib/server/textGeneration/generate.ts CHANGED
@@ -1,14 +1,10 @@
1
- import { config } from "$lib/server/config";
2
  import {
3
- MessageReasoningUpdateType,
4
  MessageUpdateType,
5
  type MessageUpdate,
6
  } from "$lib/types/MessageUpdate";
7
  import { AbortedGenerations } from "../abortedGenerations";
8
  import type { TextGenerationContext } from "./types";
9
  import type { EndpointMessage } from "../endpoints/endpoints";
10
- import { generateFromDefaultEndpoint } from "../generateFromDefaultEndpoint";
11
- import { generateSummaryOfReasoning } from "./reasoning";
12
  import { logger } from "../logger";
13
 
14
  type GenerateContext = Omit<TextGenerationContext, "messages"> & { messages: EndpointMessage[] };
@@ -27,29 +23,6 @@ export async function* generate(
27
  }: GenerateContext,
28
  preprompt?: string
29
  ): AsyncIterable<MessageUpdate> {
30
- // reasoning mode is false by default
31
- let reasoning = false;
32
- let reasoningBuffer = "";
33
- let lastReasoningUpdate = new Date();
34
- let status = "";
35
- const startTime = new Date();
36
- if (
37
- model.reasoning &&
38
- // if the beginToken is an empty string, the model starts in reasoning mode
39
- (model.reasoning.type === "regex" ||
40
- model.reasoning.type === "summarize" ||
41
- (model.reasoning.type === "tokens" && model.reasoning.beginToken === ""))
42
- ) {
43
- // if the model has reasoning in regex or summarize mode, it starts in reasoning mode
44
- // and we extract the answer from the reasoning
45
- reasoning = true;
46
- yield {
47
- type: MessageUpdateType.Reasoning,
48
- subtype: MessageReasoningUpdateType.Status,
49
- status: "Started reasoning...",
50
- };
51
- }
52
-
53
  const stream = await endpoint({
54
  messages,
55
  preprompt,
@@ -89,161 +62,19 @@ export async function* generate(
89
  text = text.slice(0, text.length - stopToken.length);
90
  }
91
 
92
- let finalAnswer = text;
93
- if (model.reasoning && model.reasoning.type === "regex") {
94
- const regex = new RegExp(model.reasoning.regex);
95
- finalAnswer = regex.exec(reasoningBuffer)?.[1] ?? text;
96
- } else if (model.reasoning && model.reasoning.type === "summarize") {
97
- yield {
98
- type: MessageUpdateType.Reasoning,
99
- subtype: MessageReasoningUpdateType.Status,
100
- status: "Summarizing reasoning...",
101
- };
102
- try {
103
- const summary = yield* generateFromDefaultEndpoint({
104
- messages: [
105
- {
106
- from: "user",
107
- content: `Question: ${
108
- messages[messages.length - 1].content
109
- }\n\nReasoning: ${reasoningBuffer}`,
110
- },
111
- ],
112
- preprompt: `Your task is to summarize concisely all your reasoning steps and then give the final answer. Keep it short, one short paragraph at most. If the reasoning steps explicitly include a code solution, make sure to include it in your answer.
113
-
114
- If the user is just having a casual conversation that doesn't require explanations, answer directly without explaining your steps, otherwise make sure to summarize step by step, make sure to skip dead-ends in your reasoning and removing excess detail.
115
-
116
- Do not use prefixes such as Response: or Answer: when answering to the user.`,
117
- generateSettings: {
118
- max_tokens: 1024,
119
- },
120
- modelId: model.id,
121
- locals,
122
- });
123
- finalAnswer = summary;
124
- yield {
125
- type: MessageUpdateType.Reasoning,
126
- subtype: MessageReasoningUpdateType.Status,
127
- status: `Done in ${Math.round((new Date().getTime() - startTime.getTime()) / 1000)}s.`,
128
- };
129
- } catch (e) {
130
- finalAnswer = text;
131
- logger.error(e);
132
- }
133
- } else if (model.reasoning && model.reasoning.type === "tokens") {
134
- // make sure to remove the content of the reasoning buffer from
135
- // the final answer to avoid duplication
136
-
137
- // if the beginToken is an empty string, we don't need to remove anything
138
- const beginIndex = model.reasoning.beginToken
139
- ? reasoningBuffer.indexOf(model.reasoning.beginToken)
140
- : 0;
141
- const endIndex = reasoningBuffer.lastIndexOf(model.reasoning.endToken);
142
-
143
- if (beginIndex !== -1 && endIndex !== -1) {
144
- // Remove the reasoning section (including tokens) from final answer
145
- finalAnswer =
146
- text.slice(0, beginIndex) + text.slice(endIndex + model.reasoning.endToken.length);
147
- }
148
- }
149
-
150
  yield {
151
  type: MessageUpdateType.FinalAnswer,
152
- text: finalAnswer,
153
  interrupted,
154
  };
155
  continue;
156
  }
157
 
158
- if (model.reasoning && model.reasoning.type === "tokens") {
159
- if (output.token.text === model.reasoning.beginToken) {
160
- reasoning = true;
161
- reasoningBuffer += output.token.text;
162
- continue;
163
- } else if (output.token.text === model.reasoning.endToken) {
164
- reasoning = false;
165
- reasoningBuffer += output.token.text;
166
- yield {
167
- type: MessageUpdateType.Reasoning,
168
- subtype: MessageReasoningUpdateType.Status,
169
- status: `Done in ${Math.round((new Date().getTime() - startTime.getTime()) / 1000)}s.`,
170
- };
171
- continue;
172
- }
173
- }
174
  // ignore special tokens
175
  if (output.token.special) continue;
176
 
177
- // pass down normal token
178
- if (reasoning) {
179
- reasoningBuffer += output.token.text;
180
-
181
- if (model.reasoning && model.reasoning.type === "tokens") {
182
- // split reasoning buffer so that anything that comes after the end token is separated
183
- // add it to the normal buffer, and yield two updates, one for the reasoning and one for the normal content
184
- // also set reasoning to false
185
-
186
- if (reasoningBuffer.lastIndexOf(model.reasoning.endToken) !== -1) {
187
- const endTokenIndex = reasoningBuffer.lastIndexOf(model.reasoning.endToken);
188
- const textBuffer = reasoningBuffer.slice(endTokenIndex + model.reasoning.endToken.length);
189
- reasoningBuffer = reasoningBuffer.slice(
190
- 0,
191
- endTokenIndex + model.reasoning.endToken.length + 1
192
- );
193
-
194
- yield {
195
- type: MessageUpdateType.Reasoning,
196
- subtype: MessageReasoningUpdateType.Stream,
197
- token: output.token.text,
198
- };
199
-
200
- yield {
201
- type: MessageUpdateType.Stream,
202
- token: textBuffer,
203
- };
204
-
205
- yield {
206
- type: MessageUpdateType.Reasoning,
207
- subtype: MessageReasoningUpdateType.Status,
208
- status: `Done in ${Math.round((new Date().getTime() - startTime.getTime()) / 1000)}s.`,
209
- };
210
-
211
- reasoning = false;
212
- continue;
213
- }
214
- }
215
- // yield status update if it has changed
216
- if (status !== "") {
217
- yield {
218
- type: MessageUpdateType.Reasoning,
219
- subtype: MessageReasoningUpdateType.Status,
220
- status,
221
- };
222
- status = "";
223
- }
224
-
225
- // create a new status every 5 seconds
226
- if (
227
- config.REASONING_SUMMARY === "true" &&
228
- new Date().getTime() - lastReasoningUpdate.getTime() > 4000
229
- ) {
230
- lastReasoningUpdate = new Date();
231
- try {
232
- generateSummaryOfReasoning(reasoningBuffer, model.id, locals).then((summary) => {
233
- status = summary;
234
- });
235
- } catch (e) {
236
- logger.error(e);
237
- }
238
- }
239
- yield {
240
- type: MessageUpdateType.Reasoning,
241
- subtype: MessageReasoningUpdateType.Stream,
242
- token: output.token.text,
243
- };
244
- } else {
245
- yield { type: MessageUpdateType.Stream, token: output.token.text };
246
- }
247
 
248
  // abort check
249
  const date = AbortedGenerations.getInstance().getAbortTime(conv._id.toString());
 
 
1
  import {
 
2
  MessageUpdateType,
3
  type MessageUpdate,
4
  } from "$lib/types/MessageUpdate";
5
  import { AbortedGenerations } from "../abortedGenerations";
6
  import type { TextGenerationContext } from "./types";
7
  import type { EndpointMessage } from "../endpoints/endpoints";
 
 
8
  import { logger } from "../logger";
9
 
10
  type GenerateContext = Omit<TextGenerationContext, "messages"> & { messages: EndpointMessage[] };
 
23
  }: GenerateContext,
24
  preprompt?: string
25
  ): AsyncIterable<MessageUpdate> {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  const stream = await endpoint({
27
  messages,
28
  preprompt,
 
62
  text = text.slice(0, text.length - stopToken.length);
63
  }
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  yield {
66
  type: MessageUpdateType.FinalAnswer,
67
+ text: text,
68
  interrupted,
69
  };
70
  continue;
71
  }
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  // ignore special tokens
74
  if (output.token.special) continue;
75
 
76
+ // yield normal token
77
+ yield { type: MessageUpdateType.Stream, token: output.token.text };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
  // abort check
80
  const date = AbortedGenerations.getInstance().getAbortTime(conv._id.toString());
src/lib/server/textGeneration/reasoning.ts DELETED
@@ -1,40 +0,0 @@
1
- import { generateFromDefaultEndpoint } from "../generateFromDefaultEndpoint";
2
- import { getReturnFromGenerator } from "$lib/utils/getReturnFromGenerator";
3
-
4
- export async function generateSummaryOfReasoning(
5
- buffer: string,
6
- modelId: string | undefined,
7
- locals: App.Locals | undefined
8
- ): Promise<string> {
9
- let summary: string | undefined;
10
-
11
- // Tools removed: no tool-based summarization path
12
-
13
- if (!summary) {
14
- summary = await getReturnFromGenerator(
15
- generateFromDefaultEndpoint({
16
- messages: [
17
- {
18
- from: "user",
19
- content: buffer.slice(-300),
20
- },
21
- ],
22
- preprompt: `You are tasked with summarizing the latest reasoning steps. Never describe results of the reasoning, only the process. Remain vague in your summary.
23
- The text might be incomplete, try your best to summarize it in one very short sentence, starting with a gerund and ending with three points.
24
- Example: "Thinking about life...", "Summarizing the results...", "Processing the input..."`,
25
- generateSettings: {
26
- max_tokens: 50,
27
- },
28
- modelId,
29
- locals,
30
- })
31
- );
32
- }
33
-
34
- if (!summary) {
35
- return "Reasoning...";
36
- }
37
-
38
- const parts = summary.split("...");
39
- return parts[0].slice(0, 100) + "...";
40
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/types/Message.ts CHANGED
@@ -8,7 +8,6 @@ export type Message = Partial<Timestamps> & {
8
  content: string;
9
  updates?: MessageUpdate[];
10
 
11
- reasoning?: string;
12
  score?: -1 | 0 | 1;
13
  /**
14
  * Either contains the base64 encoded image data
 
8
  content: string;
9
  updates?: MessageUpdate[];
10
 
 
11
  score?: -1 | 0 | 1;
12
  /**
13
  * Either contains the base64 encoded image data
src/routes/api/conversation/[id]/+server.ts CHANGED
@@ -28,7 +28,6 @@ export async function GET({ locals, params }) {
28
  // websearch removed
29
  files: message.files,
30
  updates: message.updates,
31
- reasoning: message.reasoning,
32
  })),
33
  };
34
  return Response.json(res);
 
28
  // websearch removed
29
  files: message.files,
30
  updates: message.updates,
 
31
  })),
32
  };
33
  return Response.json(res);
src/routes/conversation/[id]/+page.svelte CHANGED
@@ -9,11 +9,7 @@
9
  import { ERROR_MESSAGES, error } from "$lib/stores/errors";
10
  import { findCurrentModel } from "$lib/utils/models";
11
  import type { Message } from "$lib/types/Message";
12
- import {
13
- MessageReasoningUpdateType,
14
- MessageUpdateStatus,
15
- MessageUpdateType,
16
- } from "$lib/types/MessageUpdate";
17
  import titleUpdate from "$lib/stores/titleUpdate";
18
  import file2base64 from "$lib/utils/file2base64";
19
  import { addChildren } from "$lib/utils/tree/addChildren";
@@ -263,9 +259,6 @@
263
  // Initialize lastUpdateTime outside the loop to persist between updates
264
  let lastUpdateTime = new Date();
265
 
266
- let reasoningBuffer = "";
267
- let reasoningLastUpdate = new Date();
268
-
269
  for await (const update of messageUpdatesIterator) {
270
  if ($isAborted) {
271
  messageUpdatesAbortController.abort();
@@ -279,8 +272,6 @@
279
  }
280
 
281
  const isHighFrequencyUpdate =
282
- (update.type === MessageUpdateType.Reasoning &&
283
- update.subtype === MessageReasoningUpdateType.Stream) ||
284
  update.type === MessageUpdateType.Stream ||
285
  (update.type === MessageUpdateType.Status &&
286
  update.status === MessageUpdateStatus.KeepAlive);
@@ -324,21 +315,6 @@
324
  ...(messageToWriteTo.files ?? []),
325
  { type: "hash", value: update.sha, mime: update.mime, name: update.name },
326
  ];
327
- } else if (update.type === MessageUpdateType.Reasoning) {
328
- if (!messageToWriteTo.reasoning) {
329
- messageToWriteTo.reasoning = "";
330
- }
331
- if (update.subtype === MessageReasoningUpdateType.Stream) {
332
- reasoningBuffer += update.token;
333
- if (
334
- currentTime.getTime() - reasoningLastUpdate.getTime() >
335
- updateDebouncer.maxUpdateTime
336
- ) {
337
- messageToWriteTo.reasoning += reasoningBuffer;
338
- reasoningBuffer = "";
339
- reasoningLastUpdate = currentTime;
340
- }
341
- }
342
  } else if (update.type === MessageUpdateType.RouterMetadata) {
343
  // Update router metadata immediately when received
344
  messageToWriteTo.routerMetadata = {
 
9
  import { ERROR_MESSAGES, error } from "$lib/stores/errors";
10
  import { findCurrentModel } from "$lib/utils/models";
11
  import type { Message } from "$lib/types/Message";
12
+ import { MessageUpdateStatus, MessageUpdateType } from "$lib/types/MessageUpdate";
 
 
 
 
13
  import titleUpdate from "$lib/stores/titleUpdate";
14
  import file2base64 from "$lib/utils/file2base64";
15
  import { addChildren } from "$lib/utils/tree/addChildren";
 
259
  // Initialize lastUpdateTime outside the loop to persist between updates
260
  let lastUpdateTime = new Date();
261
 
 
 
 
262
  for await (const update of messageUpdatesIterator) {
263
  if ($isAborted) {
264
  messageUpdatesAbortController.abort();
 
272
  }
273
 
274
  const isHighFrequencyUpdate =
 
 
275
  update.type === MessageUpdateType.Stream ||
276
  (update.type === MessageUpdateType.Status &&
277
  update.status === MessageUpdateStatus.KeepAlive);
 
315
  ...(messageToWriteTo.files ?? []),
316
  { type: "hash", value: update.sha, mime: update.mime, name: update.name },
317
  ];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
  } else if (update.type === MessageUpdateType.RouterMetadata) {
319
  // Update router metadata immediately when received
320
  messageToWriteTo.routerMetadata = {
src/routes/conversation/[id]/+server.ts CHANGED
@@ -8,7 +8,6 @@ import { error } from "@sveltejs/kit";
8
  import { ObjectId } from "mongodb";
9
  import { z } from "zod";
10
  import {
11
- MessageReasoningUpdateType,
12
  MessageUpdateStatus,
13
  MessageUpdateType,
14
  type MessageUpdate,
@@ -349,12 +348,6 @@ export async function POST({ request, locals, params, getClientAddress }) {
349
  lastTokenTimestamp = new Date();
350
  }
351
  lastTokenTimestamp = new Date();
352
- } else if (
353
- event.type === MessageUpdateType.Reasoning &&
354
- event.subtype === MessageReasoningUpdateType.Stream
355
- ) {
356
- messageToWriteTo.reasoning ??= "";
357
- messageToWriteTo.reasoning += event.token;
358
  }
359
 
360
  // Set the title
@@ -399,10 +392,6 @@ export async function POST({ request, locals, params, getClientAddress }) {
399
  !(
400
  event.type === MessageUpdateType.Status &&
401
  event.status === MessageUpdateStatus.KeepAlive
402
- ) &&
403
- !(
404
- event.type === MessageUpdateType.Reasoning &&
405
- event.subtype === MessageReasoningUpdateType.Stream
406
  )
407
  ) {
408
  messageToWriteTo?.updates?.push(event);
 
8
  import { ObjectId } from "mongodb";
9
  import { z } from "zod";
10
  import {
 
11
  MessageUpdateStatus,
12
  MessageUpdateType,
13
  type MessageUpdate,
 
348
  lastTokenTimestamp = new Date();
349
  }
350
  lastTokenTimestamp = new Date();
 
 
 
 
 
 
351
  }
352
 
353
  // Set the title
 
392
  !(
393
  event.type === MessageUpdateType.Status &&
394
  event.status === MessageUpdateStatus.KeepAlive
 
 
 
 
395
  )
396
  ) {
397
  messageToWriteTo?.updates?.push(event);
src/routes/conversation/[id]/message/[messageId]/prompt/+server.ts CHANGED
@@ -59,7 +59,6 @@ export async function GET({ params, locals }) {
59
  content: msg.content,
60
  createdAt: msg.createdAt,
61
  updatedAt: msg.updatedAt,
62
- reasoning: msg.reasoning,
63
  updates: msg.updates?.filter((u) => u.type === "title"),
64
  files: msg.files,
65
  })),
 
59
  content: msg.content,
60
  createdAt: msg.createdAt,
61
  updatedAt: msg.updatedAt,
 
62
  updates: msg.updates?.filter((u) => u.type === "title"),
63
  files: msg.files,
64
  })),
src/routes/models/+page.svelte CHANGED
@@ -7,7 +7,9 @@
7
 
8
  import CarbonHelpFilled from "~icons/carbon/help-filled";
9
  import CarbonView from "~icons/carbon/view";
 
10
  import { useSettingsStore } from "$lib/stores/settings";
 
11
  interface Props {
12
  data: PageData;
13
  }
@@ -98,27 +100,19 @@
98
  <CarbonView class="text-xxs text-blue-700 dark:text-blue-500" />
99
  </span>
100
  {/if}
101
- {#if model.reasoning}
102
- <span
103
- title="This model supports reasoning."
104
- class="ml-auto grid size-[21px] place-items-center rounded-lg border border-purple-300 dark:border-purple-700"
105
- aria-label="Model supports reasoning"
106
- role="img"
107
- >
108
- <svg
109
- xmlns="http://www.w3.org/2000/svg"
110
- width="14"
111
- height="14"
112
- viewBox="0 0 32 32"
113
- >
114
- <path
115
- class="stroke-purple-700"
116
- style="stroke-width: 2; fill: none; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 50;"
117
- d="M16 6v3.33M16 6c0-2.65 3.25-4.3 5.4-2.62 1.2.95 1.6 2.65.95 4.04a3.63 3.63 0 0 1 4.61.16 3.45 3.45 0 0 1 .46 4.37 5.32 5.32 0 0 1 1.87 4.75c-.22 1.66-1.39 3.6-3.07 4.14M16 6c0-2.65-3.25-4.3-5.4-2.62a3.37 3.37 0 0 0-.95 4.04 3.65 3.65 0 0 0-4.6.16 3.37 3.37 0 0 0-.49 4.27 5.57 5.57 0 0 0-1.85 4.85 5.3 5.3 0 0 0 3.07 4.15M16 9.33v17.34m0-17.34c0 2.18 1.82 4 4 4m6.22 7.5c.67 1.3.56 2.91-.27 4.11a4.05 4.05 0 0 1-4.62 1.5c0 1.53-1.05 2.9-2.66 2.9A2.7 2.7 0 0 1 16 26.66m10.22-5.83a4.05 4.05 0 0 0-3.55-2.17m-16.9 2.18a4.05 4.05 0 0 0 .28 4.1c1 1.44 2.92 2.09 4.59 1.5 0 1.52 1.12 2.88 2.7 2.88A2.7 2.7 0 0 0 16 26.67M5.78 20.85a4.04 4.04 0 0 1 3.55-2.18"
118
- />
119
- </svg>
120
- </span>
121
- {/if}
122
  {#if model.id === $settings.activeModel}
123
  <span
124
  class="rounded-full bg-black px-2 py-0.5 text-xs text-white dark:bg-white dark:text-black"
 
7
 
8
  import CarbonHelpFilled from "~icons/carbon/help-filled";
9
  import CarbonView from "~icons/carbon/view";
10
+ import CarbonSettings from "~icons/carbon/settings";
11
  import { useSettingsStore } from "$lib/stores/settings";
12
+ import { goto } from "$app/navigation";
13
  interface Props {
14
  data: PageData;
15
  }
 
100
  <CarbonView class="text-xxs text-blue-700 dark:text-blue-500" />
101
  </span>
102
  {/if}
103
+ <button
104
+ type="button"
105
+ title="Model settings"
106
+ aria-label="Model settings for {model.displayName}"
107
+ class="flex size-[21px] items-center justify-center rounded-md border border-gray-300 text-xs text-gray-600 hover:bg-gray-100 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-700"
108
+ onclick={(e) => {
109
+ e.preventDefault();
110
+ e.stopPropagation();
111
+ goto(`${base}/settings/${model.id}`);
112
+ }}
113
+ >
114
+ <CarbonSettings class="text-xs" />
115
+ </button>
 
 
 
 
 
 
 
 
116
  {#if model.id === $settings.activeModel}
117
  <span
118
  class="rounded-full bg-black px-2 py-0.5 text-xs text-white dark:bg-white dark:text-black"