Skip to content

Commit e0ab77c

Browse files
authored
fix: token count error (#6680)
1 parent 7a36ed2 commit e0ab77c

File tree

3 files changed

+50
-30
lines changed

3 files changed

+50
-30
lines changed

web-app/src/hooks/useTokensCount.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ThreadMessage, ContentType } from '@janhq/core'
33
import { useServiceHub } from './useServiceHub'
44
import { useModelProvider } from './useModelProvider'
55
import { usePrompt } from './usePrompt'
6+
import { removeReasoningContent } from '@/utils/reasoning'
67

78
export interface TokenCountData {
89
tokenCount: number
@@ -69,7 +70,19 @@ export const useTokensCount = (
6970
} as ThreadMessage)
7071
}
7172
}
72-
return result
73+
return result.map((e) => ({
74+
...e,
75+
content: e.content.map((c) => ({
76+
...c,
77+
text:
78+
c.type === 'text'
79+
? {
80+
value: removeReasoningContent(c.text?.value ?? '.'),
81+
annotations: [],
82+
}
83+
: c.text,
84+
})),
85+
}))
7386
}, [messages, prompt, uploadedFiles])
7487

7588
// Debounced calculation that includes current prompt

web-app/src/lib/messages.ts

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { ChatCompletionMessageParam } from 'token.js'
33
import { ChatCompletionMessageToolCall } from 'openai/resources'
44
import { ThreadMessage } from '@janhq/core'
5+
import { removeReasoningContent } from '@/utils/reasoning'
56

67
/**
78
* @fileoverview Helper functions for creating chat completion request.
@@ -24,7 +25,7 @@ export class CompletionMessagesBuilder {
2425
if (msg.role === 'assistant') {
2526
return {
2627
role: msg.role,
27-
content: this.normalizeContent(
28+
content: removeReasoningContent(
2829
msg.content[0]?.text?.value || '.'
2930
),
3031
} as ChatCompletionMessageParam
@@ -135,7 +136,7 @@ export class CompletionMessagesBuilder {
135136
) {
136137
this.messages.push({
137138
role: 'assistant',
138-
content: this.normalizeContent(content),
139+
content: removeReasoningContent(content),
139140
refusal: refusal,
140141
tool_calls: calls,
141142
})
@@ -202,30 +203,4 @@ export class CompletionMessagesBuilder {
202203

203204
return result
204205
}
205-
/**
206-
* Normalize the content of a message by removing reasoning content.
207-
* This is useful to ensure that reasoning content does not get sent to the model.
208-
* @param content
209-
* @returns
210-
*/
211-
private normalizeContent = (content: string): string => {
212-
// Reasoning content should not be sent to the model
213-
if (content.includes('<think>')) {
214-
const match = content.match(/<think>([\s\S]*?)<\/think>/)
215-
if (match?.index !== undefined) {
216-
const splitIndex = match.index + match[0].length
217-
content = content.slice(splitIndex).trim()
218-
}
219-
}
220-
if (content.includes('<|channel|>analysis<|message|>')) {
221-
const match = content.match(
222-
/<\|channel\|>analysis<\|message\|>([\s\S]*?)<\|start\|>assistant<\|channel\|>final<\|message\|>/
223-
)
224-
if (match?.index !== undefined) {
225-
const splitIndex = match.index + match[0].length
226-
content = content.slice(splitIndex).trim()
227-
}
228-
}
229-
return content
230-
}
231206
}

web-app/src/utils/reasoning.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,42 @@ import {
66
} from '@janhq/core'
77

88
// Helper function to get reasoning content from an object
9-
function getReasoning(obj: { reasoning_content?: string | null; reasoning?: string | null } | null | undefined): string | null {
9+
function getReasoning(
10+
obj:
11+
| { reasoning_content?: string | null; reasoning?: string | null }
12+
| null
13+
| undefined
14+
): string | null {
1015
return obj?.reasoning_content ?? obj?.reasoning ?? null
1116
}
1217

18+
/**
19+
* Normalize the content of a message by removing reasoning content.
20+
* This is useful to ensure that reasoning content does not get sent to the model.
21+
* @param content
22+
* @returns
23+
*/
24+
export function removeReasoningContent(content: string): string {
25+
// Reasoning content should not be sent to the model
26+
if (content.includes('<think>')) {
27+
const match = content.match(/<think>([\s\S]*?)<\/think>/)
28+
if (match?.index !== undefined) {
29+
const splitIndex = match.index + match[0].length
30+
content = content.slice(splitIndex).trim()
31+
}
32+
}
33+
if (content.includes('<|channel|>analysis<|message|>')) {
34+
const match = content.match(
35+
/<\|channel\|>analysis<\|message\|>([\s\S]*?)<\|start\|>assistant<\|channel\|>final<\|message\|>/
36+
)
37+
if (match?.index !== undefined) {
38+
const splitIndex = match.index + match[0].length
39+
content = content.slice(splitIndex).trim()
40+
}
41+
}
42+
return content
43+
}
44+
1345
// Extract reasoning from a message (for completed responses)
1446
export function extractReasoningFromMessage(
1547
message: chatCompletionRequestMessage | ChatCompletionMessage

0 commit comments

Comments
 (0)