Skip to content

Commit 6d760d5

Browse files
MDL-88314 aiplacement_editor: Strip think tags from AI-generated text
1 parent 68f0f50 commit 6d760d5

2 files changed

Lines changed: 50 additions & 2 deletions

File tree

public/ai/placement/editor/classes/external/generate_text.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,14 @@ public static function execute(
9191
// Send the action to the AI manager.
9292
$manager = \core\di::get(\core_ai\manager::class);
9393
$response = $manager->process_action($action);
94+
$generatedcontent = $response->get_response_data()['generatedcontent'] ?? '';
95+
// Strip <think>...</think> reasoning blocks emitted by some models
96+
// (e.g. qwen3-32b) before returning to the client.
97+
$generatedcontent = trim(preg_replace('/<think>.*?<\/think>/is', '', $generatedcontent) ?? $generatedcontent);
9498
// Return the response.
9599
return [
96100
'success' => $response->get_success(),
97-
'generatedcontent' => $response->get_response_data()['generatedcontent'] ?? '',
101+
'generatedcontent' => $generatedcontent,
98102
'finishreason' => $response->get_response_data()['finishreason'] ?? '',
99103
'errorcode' => $response->get_errorcode(),
100104
'error' => $response->get_error(),
@@ -128,7 +132,7 @@ public static function execute_returns(): external_function_parameters {
128132
VALUE_REQUIRED,
129133
),
130134
'generatedcontent' => new external_value(
131-
PARAM_TEXT,
135+
PARAM_RAW,
132136
'The text generated by AI.',
133137
VALUE_DEFAULT,
134138
),

public/ai/placement/editor/tests/external/generate_text_test.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,50 @@
2525
* @covers \aiplacement_editor\external\generate_text
2626
*/
2727
final class generate_text_test extends \advanced_testcase {
28+
/**
29+
* Test generate_text webservice with think tags in the response.
30+
*/
31+
public function test_execute_with_think_tags(): void {
32+
$this->resetAfterTest();
33+
set_config('enabled', 1, 'aiplacement_editor');
34+
$this->setAdminUser();
35+
36+
$context = \core\context\system::instance();
37+
38+
$generatedcontent = '<think>Some internal reasoning.</think>The actual response.';
39+
40+
$response = new \core_ai\aiactions\responses\response_generate_text(success: true);
41+
$response->set_response_data(
42+
[
43+
'generatedcontent' => $generatedcontent,
44+
'finishreason' => 'stop',
45+
]
46+
);
47+
48+
$mockmanager = $this->createMock(\core_ai\manager::class);
49+
$mockmanager->method('process_action')->willReturn($response);
50+
$mockmanager->method('is_action_available')->willReturn(true);
51+
$mockmanager->method('is_action_enabled')->willReturn(true);
52+
$mockmanager->method('is_action_enabled_in_context')->willReturn(true);
53+
\core\di::set(\core_ai\manager::class, function () use ($mockmanager) {
54+
return $mockmanager;
55+
});
56+
57+
$_POST['sesskey'] = sesskey();
58+
$params = [
59+
'contextid' => $context->id,
60+
'prompttext' => 'Say hello.',
61+
];
62+
63+
$result = \core_external\external_api::call_external_function(
64+
'aiplacement_editor_generate_text',
65+
$params,
66+
);
67+
68+
$this->assertFalse($result['error']);
69+
$this->assertEquals('The actual response.', $result['data']['generatedcontent']);
70+
}
71+
2872
/**
2973
* Test generate_text webservice.
3074
*/

0 commit comments

Comments
 (0)