feat(frontend): add always-visible '重新生成分析' button per module\nfix(backend): inject dependency context for single-module generation (final_conclusion placeholders)

This commit is contained in:
xucheng 2025-10-31 03:09:43 +00:00
parent 1e904eb7f4
commit 8b5d5f5777
3 changed files with 79 additions and 1 deletions

View File

@ -669,13 +669,77 @@ async def generate_analysis(
# Initialize analysis client with configured model # Initialize analysis client with configured model
client = AnalysisClient(api_key=api_key, base_url=base_url, model=model) client = AnalysisClient(api_key=api_key, base_url=base_url, model=model)
# Prepare dependency context for single-module generation
# If the requested module declares dependencies, generate them first and inject their outputs
context = {}
try:
dependencies = analysis_cfg.get("dependencies", []) or []
if dependencies:
# Load full modules config to resolve dependency graph
analysis_config_full = load_analysis_config()
modules_config = analysis_config_full.get("analysis_modules", {})
# Collect all transitive dependencies
all_required = set()
def collect_all_deps(mod_name: str):
for dep in modules_config.get(mod_name, {}).get("dependencies", []) or []:
if dep not in all_required:
all_required.add(dep)
collect_all_deps(dep)
for dep in dependencies:
all_required.add(dep)
collect_all_deps(dep)
# Build subgraph and topologically sort
graph = {name: [d for d in (modules_config.get(name, {}).get("dependencies", []) or []) if d in all_required] for name in all_required}
in_degree = {u: 0 for u in graph}
for u, deps in graph.items():
for v in deps:
in_degree[v] += 1
queue = [u for u, deg in in_degree.items() if deg == 0]
order = []
while queue:
u = queue.pop(0)
order.append(u)
for v in graph.get(u, []):
in_degree[v] -= 1
if in_degree[v] == 0:
queue.append(v)
if len(order) != len(graph):
# Fallback: if cycle detected, just use any order
order = list(all_required)
# Generate dependencies in order
completed = {}
for mod in order:
cfg = modules_config.get(mod, {})
dep_ctx = {d: completed.get(d, "") for d in (cfg.get("dependencies", []) or [])}
dep_client = AnalysisClient(api_key=api_key, base_url=base_url, model=cfg.get("model", model))
dep_result = await dep_client.generate_analysis(
analysis_type=mod,
company_name=company_name,
ts_code=ts_code,
prompt_template=cfg.get("prompt_template", ""),
financial_data=financial_data,
context=dep_ctx,
)
completed[mod] = dep_result.get("content", "") if dep_result.get("success") else ""
context = {dep: completed.get(dep, "") for dep in dependencies}
except Exception:
# Best-effort context; if anything goes wrong, continue without it
context = {}
# Generate analysis # Generate analysis
result = await client.generate_analysis( result = await client.generate_analysis(
analysis_type=analysis_type, analysis_type=analysis_type,
company_name=company_name, company_name=company_name,
ts_code=ts_code, ts_code=ts_code,
prompt_template=prompt_template, prompt_template=prompt_template,
financial_data=financial_data financial_data=financial_data,
context=context,
) )
logger.info(f"[API] Analysis generation completed, success={result.get('success')}") logger.info(f"[API] Analysis generation completed, success={result.get('success')}")

View File

@ -1491,6 +1491,7 @@ export default function ReportPage() {
: '待开始'} : '待开始'}
</div> </div>
</div> </div>
{/* 失败时的“重新分析”按钮(兼容原逻辑) */}
{state.error && !state.loading && ( {state.error && !state.loading && (
<Button <Button
variant="outline" variant="outline"
@ -1502,6 +1503,18 @@ export default function ReportPage() {
</Button> </Button>
)} )}
{/* 新增:始终可见的“重新生成分析”按钮 */}
{!state.loading && (
<Button
variant="ghost"
size="sm"
onClick={() => retryAnalysis(analysisType)}
disabled={currentAnalysisTask !== null}
>
<RotateCw className="size-4" />
</Button>
)}
</div> </div>
{state.error && ( {state.error && (

View File

@ -8,3 +8,4 @@ echo "All pm2 applications stopped."
echo "Deleting all pm2 processes..." echo "Deleting all pm2 processes..."
pm2 delete all pm2 delete all
echo "All pm2 processes deleted." echo "All pm2 processes deleted."