Spaces:
Running
Running
| export interface ThoughtStream { | |
| content: string; | |
| reasoning: string; | |
| isThinking: boolean; | |
| hasReasoning: boolean; | |
| } | |
| const OPEN = '<think>'; | |
| const CLOSE = '</think>'; | |
| function trimBoundary(value: string): string { | |
| return value.replace(/^\n+|\n+$/g, ''); | |
| } | |
| function partialMarkerLength(value: string, marker: string): number { | |
| const maximum = Math.min(value.length, marker.length - 1); | |
| for (let length = maximum; length > 0; length -= 1) { | |
| if (value.endsWith(marker.slice(0, length))) return length; | |
| } | |
| return 0; | |
| } | |
| export function parseThoughtStream(value: string): ThoughtStream { | |
| const opening = value.indexOf(OPEN); | |
| const closing = value.indexOf(CLOSE, opening >= 0 ? opening + OPEN.length : 0); | |
| if (opening >= 0) { | |
| if (closing >= 0) { | |
| return { | |
| content: trimBoundary(value.slice(0, opening) + value.slice(closing + CLOSE.length)), | |
| reasoning: trimBoundary(value.slice(opening + OPEN.length, closing)), | |
| isThinking: false, | |
| hasReasoning: true, | |
| }; | |
| } | |
| const partialClose = partialMarkerLength(value, CLOSE); | |
| return { | |
| content: trimBoundary(value.slice(0, opening)), | |
| reasoning: trimBoundary(value.slice(opening + OPEN.length, value.length - partialClose)), | |
| isThinking: true, | |
| hasReasoning: true, | |
| }; | |
| } | |
| // Some llama.cpp chat templates put the opening marker in the prompt, so | |
| // only the closing marker appears in generated text. | |
| if (closing >= 0) { | |
| return { | |
| content: trimBoundary(value.slice(closing + CLOSE.length)), | |
| reasoning: trimBoundary(value.slice(0, closing)), | |
| isThinking: false, | |
| hasReasoning: true, | |
| }; | |
| } | |
| const partialOpen = partialMarkerLength(value, OPEN); | |
| return { | |
| content: value.slice(0, value.length - partialOpen), | |
| reasoning: '', | |
| isThinking: false, | |
| hasReasoning: false, | |
| }; | |
| } | |