feat: Improve expert diversity and description reliability
- Add random seed and diversity hints to expert generation prompt - Explicitly avoid common professions (醫生、工程師、教師、律師等) - Change description generation from batch to one-by-one for reliability - Increase default temperature from 0.7 to 0.95 for more creative output - Add description_progress SSE event for real-time feedback 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,7 @@ from ..models.schemas import (
|
||||
from ..prompts.expert_transformation_prompt import (
|
||||
get_expert_generation_prompt,
|
||||
get_expert_keyword_generation_prompt,
|
||||
get_expert_batch_description_prompt,
|
||||
get_single_description_prompt,
|
||||
)
|
||||
from ..services.llm_service import ollama_provider, extract_json_from_response
|
||||
|
||||
@@ -119,34 +119,48 @@ async def generate_expert_transformation_events(
|
||||
yield f"event: error\ndata: {json.dumps({'error': '無法生成關鍵字'}, ensure_ascii=False)}\n\n"
|
||||
return
|
||||
|
||||
# ========== Step 2: Generate descriptions for each expert keyword ==========
|
||||
yield f"event: description_start\ndata: {json.dumps({'message': '為專家關鍵字生成創新應用描述...'}, ensure_ascii=False)}\n\n"
|
||||
# ========== Step 2: Generate descriptions one by one ==========
|
||||
yield f"event: description_start\ndata: {json.dumps({'message': '為專家關鍵字生成創新應用描述...', 'total': len(all_expert_keywords)}, ensure_ascii=False)}\n\n"
|
||||
|
||||
descriptions: List[ExpertTransformationDescription] = []
|
||||
|
||||
try:
|
||||
desc_prompt = get_expert_batch_description_prompt(
|
||||
query=request.query,
|
||||
category=request.category,
|
||||
expert_keywords=[kw.model_dump() for kw in all_expert_keywords]
|
||||
)
|
||||
logger.info(f"Description prompt: {desc_prompt[:300]}")
|
||||
# Build expert lookup for domain info
|
||||
expert_lookup = {exp.id: exp for exp in experts}
|
||||
|
||||
desc_response = await ollama_provider.generate(
|
||||
desc_prompt, model=model, temperature=temperature
|
||||
)
|
||||
logger.info(f"Description response: {desc_response[:500]}")
|
||||
for idx, kw in enumerate(all_expert_keywords):
|
||||
try:
|
||||
expert = expert_lookup.get(kw.expert_id)
|
||||
expert_domain = expert.domain if expert else ""
|
||||
|
||||
desc_data = extract_json_from_response(desc_response)
|
||||
descriptions_raw = desc_data.get("descriptions", [])
|
||||
desc_prompt = get_single_description_prompt(
|
||||
query=request.query,
|
||||
keyword=kw.keyword,
|
||||
expert_id=kw.expert_id,
|
||||
expert_name=kw.expert_name,
|
||||
expert_domain=expert_domain
|
||||
)
|
||||
|
||||
for desc in descriptions_raw:
|
||||
if isinstance(desc, dict) and all(k in desc for k in ["keyword", "expert_id", "expert_name", "description"]):
|
||||
descriptions.append(ExpertTransformationDescription(**desc))
|
||||
desc_response = await ollama_provider.generate(
|
||||
desc_prompt, model=model, temperature=temperature
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to generate descriptions: {e}")
|
||||
# Continue without descriptions - at least we have keywords
|
||||
desc_data = extract_json_from_response(desc_response)
|
||||
desc_text = desc_data.get("description", "")
|
||||
|
||||
if desc_text:
|
||||
descriptions.append(ExpertTransformationDescription(
|
||||
keyword=kw.keyword,
|
||||
expert_id=kw.expert_id,
|
||||
expert_name=kw.expert_name,
|
||||
description=desc_text
|
||||
))
|
||||
|
||||
# Send progress update
|
||||
yield f"event: description_progress\ndata: {json.dumps({'current': idx + 1, 'total': len(all_expert_keywords), 'keyword': kw.keyword}, ensure_ascii=False)}\n\n"
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to generate description for '{kw.keyword}': {e}")
|
||||
# Continue with next keyword
|
||||
|
||||
yield f"event: description_complete\ndata: {json.dumps({'count': len(descriptions)}, ensure_ascii=False)}\n\n"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user