mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-21 09:17:53 +00:00
feat: add default systemPromptMappings for Qwen models
- Add default systemPromptMappings configuration for qwen3-coder-plus model - Support DashScope compatible mode API endpoints - Include Qwen coder system prompt template with git repository and sandbox placeholders - Add comprehensive test coverage for default and custom systemPromptMappings - Update documentation to reflect the new default configuration behavior - Ensure backward compatibility with existing user configurations
This commit is contained in:
@@ -154,6 +154,11 @@ export interface ConfigParameters {
|
||||
temperature?: number;
|
||||
max_tokens?: number;
|
||||
};
|
||||
systemPromptMappings?: Array<{
|
||||
baseUrls?: string[];
|
||||
modelNames?: string[];
|
||||
template?: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export class Config {
|
||||
@@ -204,6 +209,11 @@ export class Config {
|
||||
temperature?: number;
|
||||
max_tokens?: number;
|
||||
};
|
||||
private readonly systemPromptMappings?: Array<{
|
||||
baseUrls?: string[];
|
||||
modelNames?: string[];
|
||||
template?: string;
|
||||
}>;
|
||||
private modelSwitchedDuringSession: boolean = false;
|
||||
private readonly maxSessionTurns: number;
|
||||
private readonly listExtensions: boolean;
|
||||
@@ -258,6 +268,7 @@ export class Config {
|
||||
this.ideMode = params.ideMode ?? false;
|
||||
this.enableOpenAILogging = params.enableOpenAILogging ?? false;
|
||||
this.sampling_params = params.sampling_params;
|
||||
this.systemPromptMappings = params.systemPromptMappings;
|
||||
|
||||
if (params.contextFileName) {
|
||||
setGeminiMdFilename(params.contextFileName);
|
||||
@@ -540,6 +551,16 @@ export class Config {
|
||||
return this.enableOpenAILogging;
|
||||
}
|
||||
|
||||
getSystemPromptMappings():
|
||||
| Array<{
|
||||
baseUrls?: string[];
|
||||
modelNames?: string[];
|
||||
template?: string;
|
||||
}>
|
||||
| undefined {
|
||||
return this.systemPromptMappings;
|
||||
}
|
||||
|
||||
async refreshMemory(): Promise<{ memoryContent: string; fileCount: number }> {
|
||||
const { memoryContent, fileCount } = await loadServerHierarchicalMemory(
|
||||
this.getWorkingDir(),
|
||||
|
||||
@@ -238,7 +238,10 @@ export class GeminiClient {
|
||||
];
|
||||
try {
|
||||
const userMemory = this.config.getUserMemory();
|
||||
const systemInstruction = getCoreSystemPrompt(userMemory);
|
||||
const systemPromptMappings = this.config.getSystemPromptMappings();
|
||||
const systemInstruction = getCoreSystemPrompt(userMemory, {
|
||||
systemPromptMappings,
|
||||
});
|
||||
const generateContentConfigWithThinking = isThinkingSupported(
|
||||
this.config.getModel(),
|
||||
)
|
||||
@@ -354,7 +357,10 @@ export class GeminiClient {
|
||||
model || this.config.getModel() || DEFAULT_GEMINI_FLASH_MODEL;
|
||||
try {
|
||||
const userMemory = this.config.getUserMemory();
|
||||
const systemInstruction = getCoreSystemPrompt(userMemory);
|
||||
const systemPromptMappings = this.config.getSystemPromptMappings();
|
||||
const systemInstruction = getCoreSystemPrompt(userMemory, {
|
||||
systemPromptMappings,
|
||||
});
|
||||
const requestConfig = {
|
||||
abortSignal,
|
||||
...this.generateContentConfig,
|
||||
@@ -470,7 +476,10 @@ export class GeminiClient {
|
||||
|
||||
try {
|
||||
const userMemory = this.config.getUserMemory();
|
||||
const systemInstruction = getCoreSystemPrompt(userMemory);
|
||||
const systemPromptMappings = this.config.getSystemPromptMappings();
|
||||
const systemInstruction = getCoreSystemPrompt(userMemory, {
|
||||
systemPromptMappings,
|
||||
});
|
||||
|
||||
const requestConfig = {
|
||||
abortSignal,
|
||||
|
||||
@@ -18,7 +18,20 @@ import process from 'node:process';
|
||||
import { isGitRepository } from '../utils/gitUtils.js';
|
||||
import { MemoryTool, GEMINI_CONFIG_DIR } from '../tools/memoryTool.js';
|
||||
|
||||
export function getCoreSystemPrompt(userMemory?: string): string {
|
||||
export interface ModelTemplateMapping {
|
||||
baseUrls?: string[];
|
||||
modelNames?: string[];
|
||||
template?: string;
|
||||
}
|
||||
|
||||
export interface SystemPromptConfig {
|
||||
systemPromptMappings?: ModelTemplateMapping[];
|
||||
}
|
||||
|
||||
export function getCoreSystemPrompt(
|
||||
userMemory?: string,
|
||||
config?: SystemPromptConfig,
|
||||
): string {
|
||||
// if GEMINI_SYSTEM_MD is set (and not 0|false), override system prompt from file
|
||||
// default path is .qwen/system.md but can be modified via custom path in GEMINI_SYSTEM_MD
|
||||
let systemMdEnabled = false;
|
||||
@@ -34,13 +47,49 @@ export function getCoreSystemPrompt(userMemory?: string): string {
|
||||
throw new Error(`missing system prompt file '${systemMdPath}'`);
|
||||
}
|
||||
}
|
||||
if (
|
||||
process.env.OPENAI_MODEL?.startsWith('qwen3') &&
|
||||
process.env.OPENAI_BASE_URL?.includes('dashscope')
|
||||
) {
|
||||
const sandbox =
|
||||
process.env.SANDBOX === 'sandbox-exec' ? 'sandbox-exec' : '';
|
||||
return `SYSTEM_TEMPLATE:{"name":"qwen3_coder","params":{"is_git_repository":${isGitRepository(process.cwd())},"sandbox":"${sandbox}"}}`;
|
||||
|
||||
// Check for system prompt mappings from global config
|
||||
if (config?.systemPromptMappings) {
|
||||
const currentModel = process.env.OPENAI_MODEL || '';
|
||||
const currentBaseUrl = process.env.OPENAI_BASE_URL || '';
|
||||
|
||||
const matchedMapping = config.systemPromptMappings.find((mapping) => {
|
||||
const { baseUrls, modelNames } = mapping;
|
||||
// Check if baseUrl matches (when specified)
|
||||
if (
|
||||
baseUrls &&
|
||||
modelNames &&
|
||||
baseUrls.includes(currentBaseUrl) &&
|
||||
modelNames.includes(currentModel)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseUrls && baseUrls.includes(currentBaseUrl) && !modelNames) {
|
||||
return true;
|
||||
}
|
||||
if (modelNames && modelNames.includes(currentModel) && !baseUrls) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (matchedMapping?.template) {
|
||||
const sandbox =
|
||||
process.env.SANDBOX === 'sandbox-exec' ? 'sandbox-exec' : '';
|
||||
const isGitRepo = isGitRepository(process.cwd());
|
||||
|
||||
// Replace placeholders in template
|
||||
let template = matchedMapping.template;
|
||||
template = template.replace(
|
||||
'{RUNTIME_VARS_IS_GIT_REPO}',
|
||||
String(isGitRepo),
|
||||
);
|
||||
template = template.replace('{RUNTIME_VARS_SANDBOX}', sandbox);
|
||||
|
||||
return template;
|
||||
}
|
||||
}
|
||||
|
||||
const basePrompt = systemMdEnabled
|
||||
|
||||
Reference in New Issue
Block a user