Replace thinking with native Gemini thinking summaries (#400)
This uses Gemini's native [thinking summaries](https://cloud.google.com/vertex-ai/generative-ai/docs/thinking#thought-summaries) which were recently added to the API. Why? The grafted thinking would sometimes cause weird issues where the model, especially Gemini 2.5 Flash, got confused and put dyad tags like `<dyad-write>` inside the `<think>` tags. This also improves the UX because you can see the native thoughts rather than having the Gemini response load for a while without any feedback. I tried adding Anthropic extended thinking, however it requires temp to be set at 1, which isn't ideal for Dyad's use case where we need precise syntax following.
This commit is contained in:
@@ -116,6 +116,7 @@ export async function getModelClient(
|
||||
? createDyadEngine({
|
||||
apiKey: dyadApiKey,
|
||||
baseURL: dyadEngineUrl ?? "https://engine.dyad.sh/v1",
|
||||
originalProviderId: model.provider,
|
||||
dyadOptions: {
|
||||
enableLazyEdits: settings.enableProLazyEditsMode,
|
||||
enableSmartFilesContext: settings.enableProSmartFilesContextMode,
|
||||
@@ -150,7 +151,7 @@ export async function getModelClient(
|
||||
}
|
||||
: undefined,
|
||||
),
|
||||
builtinProviderId: "auto",
|
||||
builtinProviderId: model.provider,
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
|
||||
import { OpenAICompatibleChatSettings } from "@ai-sdk/openai-compatible";
|
||||
import log from "electron-log";
|
||||
import { getExtraProviderOptions } from "./thinking_utils";
|
||||
|
||||
const logger = log.scope("llm_engine_provider");
|
||||
|
||||
@@ -42,6 +43,7 @@ or to provide a custom fetch implementation for e.g. testing.
|
||||
*/
|
||||
fetch?: FetchFunction;
|
||||
|
||||
originalProviderId: string;
|
||||
dyadOptions: {
|
||||
enableLazyEdits?: boolean;
|
||||
enableSmartFilesContext?: boolean;
|
||||
@@ -113,42 +115,43 @@ export function createDyadEngine(
|
||||
defaultObjectGenerationMode:
|
||||
"tool" as LanguageModelV1ObjectGenerationMode,
|
||||
// Custom fetch implementation that adds files to the request
|
||||
fetch: files?.length
|
||||
? (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
// Use default fetch if no init or body
|
||||
if (!init || !init.body || typeof init.body !== "string") {
|
||||
return (options.fetch || fetch)(input, init);
|
||||
}
|
||||
fetch: (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
// Use default fetch if no init or body
|
||||
if (!init || !init.body || typeof init.body !== "string") {
|
||||
return (options.fetch || fetch)(input, init);
|
||||
}
|
||||
|
||||
try {
|
||||
// Parse the request body to manipulate it
|
||||
const parsedBody = JSON.parse(init.body);
|
||||
try {
|
||||
// Parse the request body to manipulate it
|
||||
const parsedBody = {
|
||||
...JSON.parse(init.body),
|
||||
...getExtraProviderOptions(options.originalProviderId),
|
||||
};
|
||||
|
||||
// Add files to the request if they exist
|
||||
if (files?.length) {
|
||||
parsedBody.dyad_options = {
|
||||
files,
|
||||
enable_lazy_edits: options.dyadOptions.enableLazyEdits,
|
||||
enable_smart_files_context:
|
||||
options.dyadOptions.enableSmartFilesContext,
|
||||
};
|
||||
}
|
||||
|
||||
// Return modified request with files included
|
||||
const modifiedInit = {
|
||||
...init,
|
||||
body: JSON.stringify(parsedBody),
|
||||
};
|
||||
|
||||
// Use the provided fetch or default fetch
|
||||
return (options.fetch || fetch)(input, modifiedInit);
|
||||
} catch (e) {
|
||||
logger.error("Error parsing request body", e);
|
||||
// If parsing fails, use original request
|
||||
return (options.fetch || fetch)(input, init);
|
||||
}
|
||||
// Add files to the request if they exist
|
||||
if (files?.length) {
|
||||
parsedBody.dyad_options = {
|
||||
files,
|
||||
enable_lazy_edits: options.dyadOptions.enableLazyEdits,
|
||||
enable_smart_files_context:
|
||||
options.dyadOptions.enableSmartFilesContext,
|
||||
};
|
||||
}
|
||||
: options.fetch,
|
||||
|
||||
// Return modified request with files included
|
||||
const modifiedInit = {
|
||||
...init,
|
||||
body: JSON.stringify(parsedBody),
|
||||
};
|
||||
|
||||
// Use the provided fetch or default fetch
|
||||
return (options.fetch || fetch)(input, modifiedInit);
|
||||
} catch (e) {
|
||||
logger.error("Error parsing request body", e);
|
||||
// If parsing fails, use original request
|
||||
return (options.fetch || fetch)(input, init);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return new OpenAICompatibleChatLanguageModel(modelId, restSettings, config);
|
||||
|
||||
18
src/ipc/utils/thinking_utils.ts
Normal file
18
src/ipc/utils/thinking_utils.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { PROVIDERS_THAT_SUPPORT_THINKING } from "../shared/language_model_helpers";
|
||||
|
||||
export function getExtraProviderOptions(
|
||||
providerId: string | undefined,
|
||||
): Record<string, any> {
|
||||
if (!providerId) {
|
||||
return {};
|
||||
}
|
||||
if (PROVIDERS_THAT_SUPPORT_THINKING.includes(providerId)) {
|
||||
return {
|
||||
thinking: {
|
||||
type: "enabled",
|
||||
include_thoughts: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
Reference in New Issue
Block a user