feat: implement mergeReasoningContent function for enhanced reasoning handling

This commit is contained in:
n4ze3m 2025-02-08 17:13:40 +05:30
parent 72eaaf9dd2
commit 8381f1c996
2 changed files with 61 additions and 15 deletions

View File

@ -40,6 +40,7 @@ import { pageAssistEmbeddingModel } from "@/models/embedding"
import { import {
isReasoningEnded, isReasoningEnded,
isReasoningStarted, isReasoningStarted,
mergeReasoningContent,
removeReasoning removeReasoning
} from "@/libs/reasoning" } from "@/libs/reasoning"
@ -652,6 +653,15 @@ export const useMessageOption = () => {
for await (const chunk of chunks) { for await (const chunk of chunks) {
contentToSave += chunk?.content contentToSave += chunk?.content
fullText += chunk?.content fullText += chunk?.content
// console.log(chunk)
// if (chunk?.reasoning_content) {
// const reasoningContent = mergeReasoningContent(
// fullText,
// chunk?.reasoning_content || ""
// )
// contentToSave += reasoningContent
// fullText += reasoningContent
// }
if (isReasoningStarted(fullText) && !reasoningStartTime) { if (isReasoningStarted(fullText) && !reasoningStartTime) {
reasoningStartTime = new Date() reasoningStartTime = new Date()

View File

@ -1,9 +1,19 @@
const tags = ["think", "reason", "reasoning", "thought"]; const tags = ["think", "reason", "reasoning", "thought"]
export function parseReasoning(text: string): { type: 'reasoning' | 'text', content: string, reasoning_running?: boolean }[] { export function parseReasoning(
text: string
): {
type: "reasoning" | "text"
content: string
reasoning_running?: boolean
}[] {
try { try {
const result: { type: 'reasoning' | 'text', content: string, reasoning_running?: boolean }[] = [] const result: {
const tagPattern = new RegExp(`<(${tags.join('|')})>`, 'i') type: "reasoning" | "text"
const closeTagPattern = new RegExp(`</(${tags.join('|')})>`, 'i') content: string
reasoning_running?: boolean
}[] = []
const tagPattern = new RegExp(`<(${tags.join("|")})>`, "i")
const closeTagPattern = new RegExp(`</(${tags.join("|")})>`, "i")
let currentIndex = 0 let currentIndex = 0
let isReasoning = false let isReasoning = false
@ -13,9 +23,12 @@ export function parseReasoning(text: string): { type: 'reasoning' | 'text', cont
const closeTagMatch = text.slice(currentIndex).match(closeTagPattern) const closeTagMatch = text.slice(currentIndex).match(closeTagPattern)
if (!isReasoning && openTagMatch) { if (!isReasoning && openTagMatch) {
const beforeText = text.slice(currentIndex, currentIndex + openTagMatch.index) const beforeText = text.slice(
currentIndex,
currentIndex + openTagMatch.index
)
if (beforeText.trim()) { if (beforeText.trim()) {
result.push({ type: 'text', content: beforeText.trim() }) result.push({ type: "text", content: beforeText.trim() })
} }
isReasoning = true isReasoning = true
@ -24,9 +37,12 @@ export function parseReasoning(text: string): { type: 'reasoning' | 'text', cont
} }
if (isReasoning && closeTagMatch) { if (isReasoning && closeTagMatch) {
const reasoningContent = text.slice(currentIndex, currentIndex + closeTagMatch.index) const reasoningContent = text.slice(
currentIndex,
currentIndex + closeTagMatch.index
)
if (reasoningContent.trim()) { if (reasoningContent.trim()) {
result.push({ type: 'reasoning', content: reasoningContent.trim() }) result.push({ type: "reasoning", content: reasoningContent.trim() })
} }
isReasoning = false isReasoning = false
@ -37,7 +53,7 @@ export function parseReasoning(text: string): { type: 'reasoning' | 'text', cont
if (currentIndex < text.length) { if (currentIndex < text.length) {
const remainingText = text.slice(currentIndex) const remainingText = text.slice(currentIndex)
result.push({ result.push({
type: isReasoning ? 'reasoning' : 'text', type: isReasoning ? "reasoning" : "text",
content: remainingText.trim(), content: remainingText.trim(),
reasoning_running: isReasoning reasoning_running: isReasoning
}) })
@ -50,7 +66,7 @@ export function parseReasoning(text: string): { type: 'reasoning' | 'text', cont
console.error(`Error parsing reasoning: ${e}`) console.error(`Error parsing reasoning: ${e}`)
return [ return [
{ {
type: 'text', type: "text",
content: text content: text
} }
] ]
@ -58,16 +74,36 @@ export function parseReasoning(text: string): { type: 'reasoning' | 'text', cont
} }
export function isReasoningStarted(text: string): boolean { export function isReasoningStarted(text: string): boolean {
const tagPattern = new RegExp(`<(${tags.join('|')})>`, 'i') const tagPattern = new RegExp(`<(${tags.join("|")})>`, "i")
return tagPattern.test(text) return tagPattern.test(text)
} }
export function isReasoningEnded(text: string): boolean { export function isReasoningEnded(text: string): boolean {
const closeTagPattern = new RegExp(`</(${tags.join('|')})>`, 'i') const closeTagPattern = new RegExp(`</(${tags.join("|")})>`, "i")
return closeTagPattern.test(text) return closeTagPattern.test(text)
} }
export function removeReasoning(text: string): string { export function removeReasoning(text: string): string {
const tagPattern = new RegExp(`<(${tags.join('|')})>.*?</(${tags.join('|')})>`, 'gis') const tagPattern = new RegExp(
return text.replace(tagPattern, '').trim() `<(${tags.join("|")})>.*?</(${tags.join("|")})>`,
"gis"
)
return text.replace(tagPattern, "").trim()
}
export function mergeReasoningContent(originalText: string, reasoning: string): string {
const defaultReasoningTag = "think"
const tagPattern = new RegExp(`<(${tags.join("|")})>(.*?)</(${tags.join("|")})>`, "is")
const hasReasoningTag = tagPattern.test(originalText)
if (hasReasoningTag) {
const match = originalText.match(tagPattern)
if (match) {
const [fullMatch, tag, existingContent] = match
const remainingText = originalText.replace(fullMatch, '').trim()
const newContent = `${existingContent.trim()}${reasoning}`
return `<${tag}>${newContent}</${tag}> ${remainingText}`
}
}
return `<${defaultReasoningTag}>${reasoning}</${defaultReasoningTag}> ${originalText.trim()}`.trim()
} }