Skip to content

Commit 95f5518

Browse files
authored
feat: add thinking mode functionality to AI widget (#9)
* feat: add thinking mode functionality to AI widget * style: remove debug logs from js files
1 parent 112aa74 commit 95f5518

6 files changed

Lines changed: 718 additions & 81 deletions

File tree

docs/sphinx_doc/source/_static/ask-ai-modules/ask-ai-api.js

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,15 @@ export class AskAIApi {
157157
* @param {Function} onComplete - Callback when complete with verified messages (userMessage, assistantMessage)
158158
* @param {Function} onError - Callback for errors (error)
159159
* @param {Function} onToolComplete - Callback when tool execution completes (callId)
160+
* @param {Object} modelConfig - Optional model configuration (e.g., { enable_thinking: true })
161+
* @param {Function} onThinkingUpdate - Callback for thinking content updates (thinkingText)
160162
*/
161-
async getAIResponseStream(message, onContentUpdate, onToolUse, onComplete, onError, onToolComplete) {
163+
async getAIResponseStream(message, onContentUpdate, onToolUse, onComplete, onError, onToolComplete, modelConfig = null, onThinkingUpdate = null) {
162164
let currentStreamContent = '';
163165
let streamMessageId = `temp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
164166
let hasReceivedContent = false;
165167
let streamCompletedSuccessfully = false;
168+
let isInReasoningPhase = false;
166169

167170
try {
168171
const requestBody = {
@@ -181,6 +184,10 @@ export class AskAIApi {
181184
user_id: this.sessionId,
182185
};
183186

187+
if (modelConfig && typeof modelConfig === 'object') {
188+
requestBody.model_params = modelConfig;
189+
}
190+
184191
console.log('Sending streaming request to:', `${this.getApiBaseUrl()}/process`);
185192

186193
const response = await fetch(`${this.getApiBaseUrl()}/process`, {
@@ -271,28 +278,70 @@ export class AskAIApi {
271278
}
272279
}
273280

274-
// Handle incremental text content
281+
// Handle reasoning phase: object="message", type="reasoning"
282+
if (data.object === "message" && data.type === "reasoning") {
283+
if (data.status === "in_progress") {
284+
isInReasoningPhase = true;
285+
console.log('Entering reasoning phase, msg_id:', data.id);
286+
} else if (data.status === "completed") {
287+
// Reasoning phase completed - ignore entirely (skip all further processing)
288+
isInReasoningPhase = false;
289+
console.log('Reasoning phase completed, msg_id:', data.id);
290+
continue;
291+
}
292+
}
293+
294+
// Handle normal message phase start: object="message", type="message"
295+
// This signals the end of reasoning and start of normal response
296+
if (data.object === "message" && data.type === "message" && data.status === "in_progress") {
297+
if (isInReasoningPhase) {
298+
isInReasoningPhase = false;
299+
console.log('Exiting reasoning phase, entering message phase');
300+
}
301+
}
302+
303+
// Skip non-delta content events (e.g., completed content summaries from reasoning)
304+
if (
305+
data.object === "content" &&
306+
data.type === "text" &&
307+
data.delta !== true &&
308+
data.status === "completed"
309+
) {
310+
console.log('Skipping completed content summary, sequence:', data.sequence_number);
311+
continue;
312+
}
313+
314+
// Handle incremental text content (used for both reasoning and normal text)
275315
if (
276316
data.object === "content" &&
277317
data.type === "text" &&
278318
data.delta === true &&
279319
data.text !== undefined
280320
) {
281-
if (!hasReceivedContent) {
282-
currentStreamContent = '';
283-
hasReceivedContent = true;
284-
}
285-
currentStreamContent += data.text;
286-
if (onContentUpdate) {
287-
onContentUpdate(currentStreamContent);
321+
if (isInReasoningPhase) {
322+
// Route to thinking callback during reasoning phase
323+
if (onThinkingUpdate) {
324+
onThinkingUpdate(data.text);
325+
}
326+
} else {
327+
// Route to normal content callback
328+
if (!hasReceivedContent) {
329+
currentStreamContent = '';
330+
hasReceivedContent = true;
331+
}
332+
currentStreamContent += data.text;
333+
if (onContentUpdate) {
334+
onContentUpdate(currentStreamContent);
335+
}
288336
}
289337
}
290338

291-
// Final message delivery
339+
// Final message delivery (skip reasoning messages to avoid showing thinking as normal text)
292340
if (
293341
data.object === "message" &&
294342
data.status === "completed" &&
295343
data.role === "assistant" &&
344+
data.type !== "reasoning" &&
296345
Array.isArray(data.content)
297346
) {
298347
const fullText = data.content

docs/sphinx_doc/source/_static/ask-ai-modules/ask-ai-i18n.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ export const I18N = {
3232
feedbackSuccess: 'Thank you for your feedback!',
3333
feedbackError: 'Failed to submit feedback',
3434
copiedSuccess: 'Copied to clipboard!',
35+
thinking: 'Thinking',
36+
thinkingTitle: 'Enable/Disable Thinking',
37+
thinkingContent: 'Thinking',
3538
helpSuffix: '\n\n---\n*If you have any questions, please visit [data-juicer issues](https://github.com/datajuicer/data-juicer/issues) or [data-juicer-agents issues](https://github.com/datajuicer/data-juicer-agents/issues)*'
3639
},
3740
zh_CN: {
@@ -63,6 +66,9 @@ export const I18N = {
6366
feedbackSuccess: '感谢您的反馈!',
6467
feedbackError: '提交反馈失败',
6568
copiedSuccess: '已复制到剪贴板!',
69+
thinking: '思考',
70+
thinkingTitle: '开启/关闭思考模式',
71+
thinkingContent: '思考',
6672
helpSuffix: '\n\n---\n*如果您有任何问题,请访问 [data-juicer issues](https://github.com/datajuicer/data-juicer/issues) 或 [data-juicer-agents issues](https://github.com/datajuicer/data-juicer-agents/issues)*'
6773
}
6874
};

0 commit comments

Comments
 (0)