mirror of
https://github.com/primedigitaltech/market-assistant.git
synced 2026-07-21 23:41:39 +08:00
refactor(frontend): 策略生成默认大模型,仅保留「本次规则稿」选项
移除「使用大模型」与保存策略偏好;buildPayload 默认 generator=llm;勾选本次仅规则稿时走 rules。后端默认 use_llm_default 改为 true。 Made-with: Cursor
This commit is contained in:
parent
7d219feb3c
commit
1229e49dbe
@ -194,8 +194,8 @@ def get_default_report_config() -> dict[str, Any]:
|
|||||||
def get_default_strategy_config() -> dict[str, Any]:
|
def get_default_strategy_config() -> dict[str, Any]:
|
||||||
"""策略生成页独立默认(与 ``report_config`` 无关),供前端回填与 PATCH 合并。"""
|
"""策略生成页独立默认(与 ``report_config`` 无关),供前端回填与 PATCH 合并。"""
|
||||||
return {
|
return {
|
||||||
# 打开页面时是否默认勾选「使用大模型生成」
|
# 默认走大模型润色;用户可在单次生成时勾选「仅规则稿」取消
|
||||||
"use_llm_default": False,
|
"use_llm_default": True,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -87,7 +87,7 @@ def validate_report_config_body(value: dict) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
_STRATEGY_CONFIG_ALLOWED_KEYS = frozenset({"use_llm_default"})
|
_STRATEGY_CONFIG_ALLOWED_KEYS = frozenset({"use_llm_default"})
|
||||||
_DEFAULT_STRATEGY_CONFIG: dict[str, bool] = {"use_llm_default": False}
|
_DEFAULT_STRATEGY_CONFIG: dict[str, bool] = {"use_llm_default": True}
|
||||||
|
|
||||||
|
|
||||||
def validate_strategy_config_body(value: dict) -> dict:
|
def validate_strategy_config_body(value: dict) -> dict:
|
||||||
|
|||||||
@ -9,7 +9,7 @@ from pipeline.serializers import validate_strategy_config_body
|
|||||||
|
|
||||||
def test_validate_strategy_config_merges_default() -> None:
|
def test_validate_strategy_config_merges_default() -> None:
|
||||||
out = validate_strategy_config_body({})
|
out = validate_strategy_config_body({})
|
||||||
assert out["use_llm_default"] is False
|
assert out["use_llm_default"] is True
|
||||||
|
|
||||||
|
|
||||||
def test_validate_strategy_config_unknown_key() -> None:
|
def test_validate_strategy_config_unknown_key() -> None:
|
||||||
|
|||||||
@ -1,12 +1,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||||
import { useRoute, useRouter, RouterLink } from 'vue-router'
|
import { useRoute, useRouter, RouterLink } from 'vue-router'
|
||||||
import {
|
import { refreshJobs, useJobs, api } from '../../composables/useJobs'
|
||||||
refreshJobs,
|
|
||||||
useJobs,
|
|
||||||
api,
|
|
||||||
strategyConfigDefaultsUrl,
|
|
||||||
} from '../../composables/useJobs'
|
|
||||||
import {
|
import {
|
||||||
generationInFlightKey,
|
generationInFlightKey,
|
||||||
withGenerationInFlight,
|
withGenerationInFlight,
|
||||||
@ -38,12 +33,8 @@ const strategyGeneratingOtherTask = computed(
|
|||||||
strategyDraftPendingJobId.value != null &&
|
strategyDraftPendingJobId.value != null &&
|
||||||
strategyDraftPendingJobId.value !== selectedId.value,
|
strategyDraftPendingJobId.value !== selectedId.value,
|
||||||
)
|
)
|
||||||
const useLlm = ref(false)
|
/** 勾选则本次仅规则稿(不调用大模型);默认不勾选即走大模型 */
|
||||||
/** 与报告页「仅规则稿」一致:勾选则本次只出规则策略稿,不调用大模型润色 */
|
|
||||||
const rulesOnlyThisRun = ref(false)
|
const rulesOnlyThisRun = ref(false)
|
||||||
const strategyDefaults = ref({ use_llm_default: false })
|
|
||||||
const strategySaveLoading = ref(false)
|
|
||||||
const strategySaveErr = ref('')
|
|
||||||
|
|
||||||
const decisions = reactive({
|
const decisions = reactive({
|
||||||
product_role: '',
|
product_role: '',
|
||||||
@ -83,7 +74,7 @@ const stanceOptions = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
function buildPayload() {
|
function buildPayload() {
|
||||||
const generator = rulesOnlyThisRun.value ? 'rules' : useLlm.value ? 'llm' : 'rules'
|
const generator = rulesOnlyThisRun.value ? 'rules' : 'llm'
|
||||||
return {
|
return {
|
||||||
generator,
|
generator,
|
||||||
business_notes: businessNotes.value,
|
business_notes: businessNotes.value,
|
||||||
@ -112,59 +103,6 @@ function formatJobOption(j) {
|
|||||||
return tail ? `#${j.id} · ${j.keyword} · ${tail}` : `#${j.id} · ${j.keyword}`
|
return tail ? `#${j.id} · ${j.keyword} · ${tail}` : `#${j.id} · ${j.keyword}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyStrategyConfigFromJob(job) {
|
|
||||||
const stored =
|
|
||||||
job && typeof job.strategy_config === 'object' && job.strategy_config !== null
|
|
||||||
? job.strategy_config
|
|
||||||
: {}
|
|
||||||
const eff = { ...strategyDefaults.value, ...stored }
|
|
||||||
useLlm.value = !!eff.use_llm_default
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadStrategyDefaults() {
|
|
||||||
try {
|
|
||||||
const r = await api(strategyConfigDefaultsUrl())
|
|
||||||
if (r.ok) {
|
|
||||||
strategyDefaults.value = await r.json()
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
/* ignore */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function saveStrategyPreferences() {
|
|
||||||
const id = selectedId.value
|
|
||||||
if (!id) return
|
|
||||||
strategySaveErr.value = ''
|
|
||||||
strategySaveLoading.value = true
|
|
||||||
try {
|
|
||||||
const r = await api(`/api/jobs/${id}/`, {
|
|
||||||
method: 'PATCH',
|
|
||||||
body: JSON.stringify({
|
|
||||||
strategy_config: { use_llm_default: useLlm.value },
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
const text = await r.text()
|
|
||||||
if (!r.ok) {
|
|
||||||
try {
|
|
||||||
const j = JSON.parse(text)
|
|
||||||
strategySaveErr.value = j.detail || text
|
|
||||||
} catch {
|
|
||||||
strategySaveErr.value = text || `HTTP ${r.status}`
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const updated = JSON.parse(text)
|
|
||||||
const idx = jobs.value.findIndex((x) => x.id === updated.id)
|
|
||||||
if (idx >= 0) jobs.value[idx] = updated
|
|
||||||
applyStrategyConfigFromJob(updated)
|
|
||||||
} catch (e) {
|
|
||||||
strategySaveErr.value = String(e)
|
|
||||||
} finally {
|
|
||||||
strategySaveLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadList() {
|
async function loadList() {
|
||||||
try {
|
try {
|
||||||
await refreshJobs()
|
await refreshJobs()
|
||||||
@ -210,10 +148,7 @@ async function generateAndGoPreview() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(loadList)
|
||||||
await loadStrategyDefaults()
|
|
||||||
await loadList()
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => route.query.job,
|
() => route.query.job,
|
||||||
@ -232,23 +167,6 @@ watch(
|
|||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
watch(selectedId, async () => {
|
|
||||||
strategySaveErr.value = ''
|
|
||||||
const id = selectedId.value
|
|
||||||
if (!id) return
|
|
||||||
try {
|
|
||||||
const r = await api(`/api/jobs/${id}/`)
|
|
||||||
if (r.ok) {
|
|
||||||
const j = await r.json()
|
|
||||||
const idx = jobs.value.findIndex((x) => x.id === j.id)
|
|
||||||
if (idx >= 0) jobs.value[idx] = j
|
|
||||||
applyStrategyConfigFromJob(j)
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
/* ignore */
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -256,20 +174,16 @@ watch(selectedId, async () => {
|
|||||||
<section class="ma-card">
|
<section class="ma-card">
|
||||||
<h2>策略生成</h2>
|
<h2>策略生成</h2>
|
||||||
<p class="hint-top">
|
<p class="hint-top">
|
||||||
选择<strong>已成功</strong>任务,在下方填空与勾选。策略页的默认选项保存在本任务的<strong>策略配置</strong>中(与「分析报告生成」页的<strong>报告配置</strong>相互独立)。未勾选大模型时由规则生成策略底稿;勾选后由大模型在底稿与同任务数据摘要基础上成稿(需服务端已配置网关)。策略稿与宿主报告第九章的归纳<strong>默认对齐</strong>(无需在此勾选)。提交后跳转到
|
选择<strong>已成功</strong>任务,在下方填空与勾选。<strong>默认</strong>使用大模型在规则底稿与同任务数据摘要基础上成稿(需服务端已配置网关)。若需更快、不调用智能服务,可勾选「本次仅生成规则稿」。策略配置与「分析报告生成」页的<strong>报告配置</strong>相互独立。策略稿与宿主报告第九章的归纳<strong>默认对齐</strong>。提交后跳转到
|
||||||
<RouterLink to="/jd/strategy-view">策略稿预览</RouterLink>
|
<RouterLink to="/jd/strategy-view">策略稿预览</RouterLink>
|
||||||
。未填项在文稿中仍保留占位提示。
|
。未填项在文稿中仍保留占位提示。
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="toolbar toolbar-col">
|
<div class="toolbar">
|
||||||
<label class="chk-inline">
|
<label class="chk-inline">
|
||||||
<input v-model="rulesOnlyThisRun" type="checkbox" />
|
<input v-model="rulesOnlyThisRun" type="checkbox" />
|
||||||
本次仅生成规则稿(不做大模型全文润色,更快、不调用智能服务)
|
本次仅生成规则稿(不做大模型全文润色,更快、不调用智能服务)
|
||||||
</label>
|
</label>
|
||||||
<label class="chk-inline">
|
|
||||||
<input v-model="useLlm" type="checkbox" :disabled="rulesOnlyThisRun" />
|
|
||||||
使用大模型生成(与上项互斥:勾选上一项时本项无效)
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<label class="sel-label">任务</label>
|
<label class="sel-label">任务</label>
|
||||||
@ -279,14 +193,6 @@ watch(selectedId, async () => {
|
|||||||
{{ formatJobOption(j) }}
|
{{ formatJobOption(j) }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="ma-btn ma-btn-secondary"
|
|
||||||
:disabled="!selectedId || strategySaveLoading"
|
|
||||||
@click="saveStrategyPreferences"
|
|
||||||
>
|
|
||||||
{{ strategySaveLoading ? '保存中…' : '保存策略偏好' }}
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="ma-btn ma-btn-primary"
|
class="ma-btn ma-btn-primary"
|
||||||
@ -296,7 +202,6 @@ watch(selectedId, async () => {
|
|||||||
{{ strategyGeneratingThisTask ? '生成中…' : '生成并前往预览' }}
|
{{ strategyGeneratingThisTask ? '生成中…' : '生成并前往预览' }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="strategySaveErr" class="ma-err">{{ strategySaveErr }}</p>
|
|
||||||
<p v-if="strategyGeneratingOtherTask" class="ma-warn-banner">
|
<p v-if="strategyGeneratingOtherTask" class="ma-warn-banner">
|
||||||
任务 #{{ strategyDraftPendingJobId }} 的策略稿正在生成中,请稍候再切换任务或重复提交。
|
任务 #{{ strategyDraftPendingJobId }} 的策略稿正在生成中,请稍候再切换任务或重复提交。
|
||||||
</p>
|
</p>
|
||||||
@ -429,10 +334,6 @@ watch(selectedId, async () => {
|
|||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
margin-bottom: 0.75rem;
|
margin-bottom: 0.75rem;
|
||||||
}
|
}
|
||||||
.toolbar-col {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: stretch;
|
|
||||||
}
|
|
||||||
.sel-label {
|
.sel-label {
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user