Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed
- [ask sb] Fixed issue where reasoning tokens would appear in `text` content for openai compatible models. [#582](https://github.com/sourcebot-dev/sourcebot/pull/582)

## [4.8.1] - 2025-10-29

### Fixed
Expand Down
1 change: 1 addition & 0 deletions docs/docs/configuration/language-model-providers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ The OpenAI compatible provider allows you to use any model that is compatible wi

<Accordion title="Troubleshooting">
- When using [llama.cpp](https://github.com/ggml-org/llama.cpp), if you hit "Failed after 3 attempts. Last error: tools param requires --jinja flag", add the `--jinja` flag to your `llama-server` command.
- If you're seeing the LLM outputing reasoning tokens wrapped in XML tags (e.g., `<reasoning>`, `<thinking>`, etc.), you can configure the `reasoningTag` parameter to the name of the tag (without angle brackets). This parameter defaults to `think`.
</Accordion>

### OpenRouter
Expand Down
20 changes: 20 additions & 0 deletions docs/snippets/schemas/v3/index.schema.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2633,6 +2633,16 @@
}
},
"additionalProperties": false
},
"reasoningTag": {
"type": "string",
"description": "The name of the XML tag to extract reasoning from (without angle brackets). Defaults to `think`.",
"default": "think",
"examples": [
"think",
"thinking",
"reasoning"
]
}
},
"required": [
Expand Down Expand Up @@ -4052,6 +4062,16 @@
}
},
"additionalProperties": false
},
"reasoningTag": {
"type": "string",
"description": "The name of the XML tag to extract reasoning from (without angle brackets). Defaults to `think`.",
"default": "think",
"examples": [
"think",
"thinking",
"reasoning"
]
}
},
"required": [
Expand Down
20 changes: 20 additions & 0 deletions docs/snippets/schemas/v3/languageModel.schema.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,16 @@
}
},
"additionalProperties": false
},
"reasoningTag": {
"type": "string",
"description": "The name of the XML tag to extract reasoning from (without angle brackets). Defaults to `think`.",
"default": "think",
"examples": [
"think",
"thinking",
"reasoning"
]
}
},
"required": [
Expand Down Expand Up @@ -2621,6 +2631,16 @@
}
},
"additionalProperties": false
},
"reasoningTag": {
"type": "string",
"description": "The name of the XML tag to extract reasoning from (without angle brackets). Defaults to `think`.",
"default": "think",
"examples": [
"think",
"thinking",
"reasoning"
]
}
},
"required": [
Expand Down
20 changes: 20 additions & 0 deletions packages/schemas/src/v3/index.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2632,6 +2632,16 @@ const schema = {
}
},
"additionalProperties": false
},
"reasoningTag": {
"type": "string",
"description": "The name of the XML tag to extract reasoning from (without angle brackets). Defaults to `think`.",
"default": "think",
"examples": [
"think",
"thinking",
"reasoning"
]
}
},
"required": [
Expand Down Expand Up @@ -4051,6 +4061,16 @@ const schema = {
}
},
"additionalProperties": false
},
"reasoningTag": {
"type": "string",
"description": "The name of the XML tag to extract reasoning from (without angle brackets). Defaults to `think`.",
"default": "think",
"examples": [
"think",
"thinking",
"reasoning"
]
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions packages/schemas/src/v3/index.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,10 @@ export interface OpenAICompatibleLanguageModel {
baseUrl: string;
headers?: LanguageModelHeaders;
queryParams?: LanguageModelQueryParams;
/**
* The name of the XML tag to extract reasoning from (without angle brackets). Defaults to `think`.
*/
reasoningTag?: string;
}
/**
* Optional query parameters to include in the request url.
Expand Down
20 changes: 20 additions & 0 deletions packages/schemas/src/v3/languageModel.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,16 @@ const schema = {
}
},
"additionalProperties": false
},
"reasoningTag": {
"type": "string",
"description": "The name of the XML tag to extract reasoning from (without angle brackets). Defaults to `think`.",
"default": "think",
"examples": [
"think",
"thinking",
"reasoning"
]
}
},
"required": [
Expand Down Expand Up @@ -2620,6 +2630,16 @@ const schema = {
}
},
"additionalProperties": false
},
"reasoningTag": {
"type": "string",
"description": "The name of the XML tag to extract reasoning from (without angle brackets). Defaults to `think`.",
"default": "think",
"examples": [
"think",
"thinking",
"reasoning"
]
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions packages/schemas/src/v3/languageModel.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,10 @@ export interface OpenAICompatibleLanguageModel {
baseUrl: string;
headers?: LanguageModelHeaders;
queryParams?: LanguageModelQueryParams;
/**
* The name of the XML tag to extract reasoning from (without angle brackets). Defaults to `think`.
*/
reasoningTag?: string;
}
/**
* Optional query parameters to include in the request url.
Expand Down
13 changes: 11 additions & 2 deletions packages/web/src/features/chat/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { ChatVisibility, OrgRole, Prisma, PrismaClient } from "@sourcebot/db";
import { LanguageModel } from "@sourcebot/schemas/v3/languageModel.type";
import { Token } from "@sourcebot/schemas/v3/shared.type";
import { loadConfig } from "@sourcebot/shared";
import { generateText, JSONValue } from "ai";
import { generateText, JSONValue, extractReasoningMiddleware, wrapLanguageModel } from "ai";
import fs from 'fs';
import { StatusCodes } from "http-status-codes";
import path from 'path';
Expand Down Expand Up @@ -568,8 +568,17 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
: undefined,
});

return {
const model = wrapLanguageModel({
model: openai.chatModel(modelId),
middleware: [
extractReasoningMiddleware({
tagName: config.reasoningTag ?? 'think',
}),
]
});

return {
model,
}
}
case 'openrouter': {
Expand Down
10 changes: 10 additions & 0 deletions schemas/v3/languageModel.json
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,16 @@
},
"queryParams": {
"$ref": "./shared.json#/definitions/LanguageModelQueryParams"
},
"reasoningTag": {
"type": "string",
"description": "The name of the XML tag to extract reasoning from (without angle brackets). Defaults to `think`.",
"default": "think",
"examples": [
"think",
"thinking",
"reasoning"
]
}
},
"required": [
Expand Down
Loading