Skip to content

Commit 1c48123

Browse files
committed
refactor: standardize max_tokens handling and introduce default constant
- Updated LLMProfile and related components to enforce max_tokens validation, ensuring values are positive and adhere to a global default. - Removed hardcoded max_tokens limits in various configurations, replacing them with a reference to DEFAULT_MAX_OUTPUT_TOKENS for consistency. - Enhanced unit tests to validate the new max_tokens behavior and ensure proper lifting of values to the global floor. - Introduced a new constants file to manage default values, improving maintainability and clarity across the codebase.
1 parent 5c84cb5 commit 1c48123

12 files changed

Lines changed: 55 additions & 14 deletions

File tree

application/ai/llm_control_service.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,14 @@ def _validate_temperature(cls, value: float) -> float:
5858
raise ValueError('temperature must be between 0 and 2')
5959
return value
6060

61-
@field_validator('max_tokens', 'timeout_seconds')
61+
@field_validator('max_tokens')
62+
@classmethod
63+
def _validate_max_tokens(cls, value: int) -> int:
64+
if value <= 0:
65+
raise ValueError('value must be positive')
66+
return max(value, DEFAULT_MAX_OUTPUT_TOKENS)
67+
68+
@field_validator('timeout_seconds')
6269
@classmethod
6370
def _validate_positive_int(cls, value: int) -> int:
6471
if value <= 0:

application/engine/dag/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ class NodeConfig(BaseModel):
199199
max_retries: int = Field(default=1, ge=0, le=5)
200200
timeout_seconds: int = Field(default=60, ge=10, le=600)
201201
temperature: float = Field(default=0.7, ge=0.0, le=2.0)
202-
max_tokens: Optional[int] = Field(default=None, ge=100, le=120000)
202+
max_tokens: Optional[int] = Field(default=None, ge=100)
203203

204204

205205
# ─── DAG 定义模型 ───

engine/runtime/daemon_host.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2012,7 +2012,7 @@ async def _stream_one_beat(
20122012
except Exception:
20132013
pass # 降级:无锚点则不加
20142014

2015-
# 输出 token 策略与整章生成一致:固定 16000,不随目标字数动态变化。
2015+
# 输出 token 策略与整章生成一致:统一走全局输出下限,不随目标字数动态变化。
20162016
from engine.runtime.generation_token_policy import CHAPTER_PROSE_MAX_TOKENS
20172017

20182018
max_tokens = CHAPTER_PROSE_MAX_TOKENS

frontend/src/components/autopilot/NodeEditorDrawer.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
v-model:value="localConfig.maxTokens"
5050
size="small"
5151
:min="100"
52-
:max="16000"
5352
:step="100"
5453
placeholder="默认"
5554
clearable

frontend/src/components/settings/sections/EngineMatrixInferenceCollapse.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
class="em-infer-input"
2121
:value="maxTokens"
2222
:min="1"
23-
:max="200000"
2423
:step="256"
2524
size="small"
2625
@update:value="onMaxTokens"
@@ -43,6 +42,8 @@
4342
</template>
4443

4544
<script setup lang="ts">
45+
import { DEFAULT_MAX_OUTPUT_TOKENS } from '@/constants/llm'
46+
4647
const props = defineProps<{
4748
temperature: number
4849
maxTokens: number
@@ -60,7 +61,7 @@ function onTemperature(v: number | null) {
6061
}
6162
6263
function onMaxTokens(v: number | null) {
63-
emit('update:maxTokens', Math.max(1, Math.floor(v ?? 4096)))
64+
emit('update:maxTokens', Math.max(1, Math.floor(v ?? DEFAULT_MAX_OUTPUT_TOKENS)))
6465
}
6566
6667
function onTimeout(v: number | null) {

frontend/src/components/settings/sections/EngineMatrixSection.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
import { computed, onMounted, reactive, ref } from 'vue'
114114
import { useMessage } from 'naive-ui'
115115
import { llmControlApi, type LLMControlPanelData, type LLMProfile, type LLMProtocol } from '@/api/llmControl'
116+
import { DEFAULT_MAX_OUTPUT_TOKENS } from '@/constants/llm'
116117
import EndpointGrid from './EngineMatrixEndpointGrid.vue'
117118
import InferenceCollapse from './EngineMatrixInferenceCollapse.vue'
118119
@@ -161,21 +162,21 @@ const formData = reactive<ModelRoleConfig>({
161162
default_model_base_url: '',
162163
default_model: '',
163164
default_temperature: 0.7,
164-
default_max_tokens: 16000,
165+
default_max_tokens: DEFAULT_MAX_OUTPUT_TOKENS,
165166
default_timeout_seconds: 300,
166167
cheap_model_provider: 'openai',
167168
cheap_model_api_key: '',
168169
cheap_model_base_url: '',
169170
cheap_model: '',
170171
cheap_temperature: 0.5,
171-
cheap_max_tokens: 16000,
172+
cheap_max_tokens: DEFAULT_MAX_OUTPUT_TOKENS,
172173
cheap_timeout_seconds: 300,
173174
knowledge_model_provider: 'openai',
174175
knowledge_model_api_key: '',
175176
knowledge_model_base_url: '',
176177
knowledge_model: '',
177178
knowledge_temperature: 0.3,
178-
knowledge_max_tokens: 16000,
179+
knowledge_max_tokens: DEFAULT_MAX_OUTPUT_TOKENS,
179180
knowledge_timeout_seconds: 300,
180181
})
181182

frontend/src/components/workbench/LLMControlPanel.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ import {
257257
type LLMRuntimeSummary,
258258
type ModelItem,
259259
} from '../../api/llmControl'
260+
import { DEFAULT_MAX_OUTPUT_TOKENS } from '@/constants/llm'
260261
import { readStorageJson, writeStorageJson } from '@/utils/storage'
261262
import { formatApiError } from '../../utils/apiError'
262263
@@ -409,7 +410,7 @@ function buildProfileFromPreset(preset?: LLMPreset): LLMProfile {
409410
api_key: '',
410411
model: preset?.default_model || '',
411412
temperature: 0.7,
412-
max_tokens: 16000,
413+
max_tokens: DEFAULT_MAX_OUTPUT_TOKENS,
413414
timeout_seconds: 300,
414415
extra_headers: {},
415416
extra_query: {},

frontend/src/constants/llm.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const DEFAULT_MAX_OUTPUT_TOKENS = 120000

infrastructure/persistence/database/schema.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ CREATE TABLE IF NOT EXISTS llm_profiles (
868868
api_key TEXT NOT NULL DEFAULT '',
869869
model TEXT NOT NULL DEFAULT '',
870870
temperature REAL NOT NULL DEFAULT 0.7,
871-
max_tokens INTEGER NOT NULL DEFAULT 4096,
871+
max_tokens INTEGER NOT NULL DEFAULT 120000,
872872
timeout_seconds INTEGER NOT NULL DEFAULT 300,
873873
extra_headers TEXT NOT NULL DEFAULT '{}',
874874
extra_query TEXT NOT NULL DEFAULT '{}',

interfaces/api/v1/engine/dag/dag_routes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ class UpdateNodeConfigRequest(BaseModel):
421421
max_retries: Optional[int] = Field(default=None, ge=0, le=5)
422422
timeout_seconds: Optional[int] = Field(default=None, ge=10, le=600)
423423
temperature: Optional[float] = Field(default=None, ge=0.0, le=2.0)
424-
max_tokens: Optional[int] = Field(default=None, ge=100, le=120000)
424+
max_tokens: Optional[int] = Field(default=None, ge=100)
425425

426426

427427
@router.put("/{novel_id}/nodes/{node_id}")

0 commit comments

Comments
 (0)