Files
novelty-seeking/backend/app/models/schemas.py
gbanyan 91f7f41bc1 feat: Add dynamic category system for attribute analysis
Backend:
- Add CategoryMode enum with 4 modes (fixed_only, fixed_plus_custom, custom_only, dynamic_auto)
- Add Step 0 for LLM category analysis before attribute generation
- Implement dynamic prompts for Step 1/2 that work with N categories
- Add execute_step0(), resolve_final_categories(), assemble_dynamic_attribute_tree()
- Update SSE events to include step0_start, step0_complete, categories_resolved

Frontend:
- Add CategorySelector component with mode selection, custom category input, and category count slider
- Update types with CategoryDefinition, Step0Result, DynamicStep1Result, DynamicCausalChain
- Update api.ts with new SSE event handlers
- Update useAttribute hook with category parameters
- Integrate CategorySelector into InputPanel
- Fix mindmap to dynamically extract and display N categories (was hardcoded to 4)
- Add CSS styles for depth 5-8 to support more category levels

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 23:04:35 +08:00

101 lines
2.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from pydantic import BaseModel
from typing import Optional, List, Dict
from enum import Enum
class AttributeNode(BaseModel):
name: str
category: Optional[str] = None # 材料, 功能, 用途, 使用族群
children: Optional[List["AttributeNode"]] = None
AttributeNode.model_rebuild()
class AnalyzeRequest(BaseModel):
query: str
model: Optional[str] = None
temperature: Optional[float] = 0.7
categories: Optional[List[str]] = None # 如果為 None使用預設類別
class AnalyzeResponse(BaseModel):
query: str
attributes: AttributeNode
class ModelListResponse(BaseModel):
models: List[str]
# ===== Multi-step streaming schemas =====
class Step1Result(BaseModel):
"""Step 1 的結果:各類別屬性列表"""
materials: List[str]
functions: List[str]
usages: List[str]
users: List[str]
class CausalChain(BaseModel):
"""單條因果鏈"""
material: str
function: str
usage: str
user: str
class StreamAnalyzeRequest(BaseModel):
"""多步驟分析請求(更新為支持動態類別)"""
query: str
model: Optional[str] = None
temperature: Optional[float] = 0.7
chain_count: int = 5 # 用戶可設定要生成多少條因果鏈
# 新增:動態類別支持
category_mode: Optional[str] = "dynamic_auto" # CategoryMode enum 值
custom_categories: Optional[List[str]] = None
suggested_category_count: int = 3 # 建議 LLM 生成的類別數量
class StreamAnalyzeResponse(BaseModel):
"""最終完整結果"""
query: str
step1_result: Step1Result
causal_chains: List[CausalChain]
attributes: AttributeNode
# ===== Dynamic category system schemas =====
class CategoryMode(str, Enum):
"""類別模式"""
FIXED_ONLY = "fixed_only"
FIXED_PLUS_CUSTOM = "fixed_plus_custom"
CUSTOM_ONLY = "custom_only"
DYNAMIC_AUTO = "dynamic_auto"
class CategoryDefinition(BaseModel):
"""類別定義"""
name: str
description: Optional[str] = None
is_fixed: bool = True # LLM 生成的為 False
order: int = 0
class Step0Result(BaseModel):
"""Step 0: LLM 分析建議類別"""
categories: List[CategoryDefinition]
class DynamicStep1Result(BaseModel):
"""動態版本的 Step 1 結果"""
attributes: Dict[str, List[str]] # {類別名: [屬性列表]}
class DynamicCausalChain(BaseModel):
"""動態版本的因果鏈"""
chain: Dict[str, str] # {類別名: 選中屬性}