tried to further improve writing quality

This commit is contained in:
2026-03-17 15:28:01 +01:00
parent d4bf3fe25d
commit b3bb67f3ad
10 changed files with 750 additions and 123 deletions

View File

@@ -1723,6 +1723,10 @@ async def post_detail_page(request: Request, post_id: str):
)
reference_posts = [p.post_text for p in linkedin_posts if p.post_text and len(p.post_text) > 100][:10]
profile_analysis = profile_analysis_record.full_analysis if profile_analysis_record else None
style_card = None
if profile_analysis and isinstance(profile_analysis, dict):
from src.agents.writer import WriterAgent
style_card = WriterAgent()._build_style_card(profile_analysis)
post_type = None
post_type_analysis = None
@@ -1762,6 +1766,7 @@ async def post_detail_page(request: Request, post_id: str):
"post_type": post_type,
"post_type_analysis": post_type_analysis,
"final_feedback": final_feedback,
"style_card": style_card,
"profile_picture_url": profile_picture_url,
"profile_picture": profile_picture_url,
"media_items_dict": media_items_dict,
@@ -3429,10 +3434,11 @@ async def company_manage_post_detail(request: Request, post_id: str, employee_id
return RedirectResponse(url="/company/manage", status_code=302)
# Get employee info + post in parallel
emp_profile, emp_user, post = await asyncio.gather(
emp_profile, emp_user, post, profile_analysis_record = await asyncio.gather(
db.get_profile(UUID(employee_id)),
db.get_user(UUID(employee_id)),
db.get_generated_post(UUID(post_id)),
db.get_profile_analysis(UUID(employee_id)),
)
if not emp_profile:
return RedirectResponse(url="/company/manage", status_code=302)
@@ -3455,6 +3461,11 @@ async def company_manage_post_detail(request: Request, post_id: str, employee_id
display_name=emp_profile.display_name
)
profile_picture_url = await get_user_avatar(emp_session, emp_profile.id)
profile_analysis = profile_analysis_record.full_analysis if profile_analysis_record else None
style_card = None
if profile_analysis and isinstance(profile_analysis, dict):
from src.agents.writer import WriterAgent
style_card = WriterAgent()._build_style_card(profile_analysis)
# Convert media_items to dicts for JSON serialization in template
media_items_dict = []
@@ -3484,6 +3495,7 @@ async def company_manage_post_detail(request: Request, post_id: str, employee_id
"post": post,
"media_items_dict": media_items_dict,
"profile_picture_url": profile_picture_url,
"style_card": style_card,
"permissions": permissions,
"current_employee_id": employee_id,
"limit_reached": limit_reached,
@@ -4373,15 +4385,22 @@ async def chat_generate_post(request: Request):
"relevance": "User-specified content"
}
strategy_weight = orchestrator._get_effective_strategy_weight(
base_weight=post_type.strategy_weight,
post_type=post_type,
post_type_analysis=post_type.analysis if post_type else None
)
plan = await orchestrator.generate_post_plan(
topic=topic,
profile_analysis=profile_analysis.full_analysis,
company_strategy=company_strategy,
strategy_weight=getattr(post_type, 'strategy_weight', 0.5),
user_thoughts=message
strategy_weight=strategy_weight,
user_thoughts=message,
post_type_analysis=post_type.analysis if post_type and post_type.analysis else None
)
if plan:
topic["post_plan"] = plan
topic["content_plan"] = plan
# Generate post
post_content = await writer.process(
@@ -4391,10 +4410,64 @@ async def chat_generate_post(request: Request):
post_type=post_type,
user_thoughts=message, # CRITICAL: User's input as primary content
company_strategy=company_strategy,
strategy_weight=post_type.strategy_weight
strategy_weight=strategy_weight
)
post_content = sanitize_post_content(post_content)
# Run critic + one revision pass for chat flow quality parity
critic_result = await orchestrator.critic.process(
post=post_content,
profile_analysis=profile_analysis.full_analysis,
topic=topic,
example_posts=example_post_texts,
iteration=1,
max_iterations=2
)
critic_result = orchestrator._normalize_critic_scores(critic_result)
if not critic_result.get("approved", False):
post_content = await writer.process(
topic=topic,
profile_analysis=profile_analysis.full_analysis,
feedback=critic_result.get("feedback", ""),
previous_version=post_content,
example_posts=example_post_texts,
critic_result=critic_result,
post_type=post_type,
user_thoughts=message,
company_strategy=company_strategy,
strategy_weight=strategy_weight
)
post_content = sanitize_post_content(post_content)
critic_result = await orchestrator.critic.process(
post=post_content,
profile_analysis=profile_analysis.full_analysis,
topic=topic,
example_posts=example_post_texts,
iteration=2,
max_iterations=2
)
critic_result = orchestrator._normalize_critic_scores(critic_result)
# Quality checks + final polish (same as wizard)
if settings.quality_refiner_enabled:
quality_checks = await orchestrator._run_quality_checks(post_content, example_post_texts)
grammar_errors = quality_checks['grammar_check'].get('error_count', 0)
style_similarity = quality_checks['style_check'].get('avg_similarity', 1.0)
readability_passed = quality_checks['readability_check'].get('passed', True)
needs_polish = (
grammar_errors > 0 or
style_similarity < 0.75 or
not readability_passed
)
if needs_polish:
post_content = await orchestrator.quality_refiner.final_polish(
post=post_content,
quality_checks=quality_checks,
profile_analysis=profile_analysis.full_analysis,
example_posts=example_post_texts
)
post_content = sanitize_post_content(post_content)
# Generate conversation ID
import uuid
conversation_id = str(uuid.uuid4())
@@ -4495,15 +4568,22 @@ async def chat_refine_post(request: Request):
"relevance": "User refinement request"
}
strategy_weight = orchestrator._get_effective_strategy_weight(
base_weight=getattr(post_type, 'strategy_weight', 0.5),
post_type=post_type,
post_type_analysis=post_type.analysis if post_type else None
)
plan = await orchestrator.generate_post_plan(
topic=topic,
profile_analysis=full_analysis,
company_strategy=company_strategy,
strategy_weight=getattr(post_type, 'strategy_weight', 0.5),
user_thoughts=message
strategy_weight=strategy_weight,
user_thoughts=message,
post_type_analysis=post_type.analysis if post_type and post_type.analysis else None
)
if plan:
topic["post_plan"] = plan
topic["content_plan"] = plan
# Use writer's revision capability
refined_post = await writer.process(
@@ -4515,10 +4595,64 @@ async def chat_refine_post(request: Request):
post_type=post_type,
user_thoughts=message,
company_strategy=company_strategy,
strategy_weight=getattr(post_type, 'strategy_weight', 0.5)
strategy_weight=strategy_weight
)
refined_post = sanitize_post_content(refined_post)
# Critic + quality checks for chat refine parity
critic_result = await orchestrator.critic.process(
post=refined_post,
profile_analysis=full_analysis,
topic=topic,
example_posts=example_post_texts,
iteration=1,
max_iterations=2
)
critic_result = orchestrator._normalize_critic_scores(critic_result)
if not critic_result.get("approved", False):
refined_post = await writer.process(
topic=topic,
profile_analysis=full_analysis,
feedback=critic_result.get("feedback", ""),
previous_version=refined_post,
example_posts=example_post_texts,
critic_result=critic_result,
post_type=post_type,
user_thoughts=message,
company_strategy=company_strategy,
strategy_weight=strategy_weight
)
refined_post = sanitize_post_content(refined_post)
critic_result = await orchestrator.critic.process(
post=refined_post,
profile_analysis=full_analysis,
topic=topic,
example_posts=example_post_texts,
iteration=2,
max_iterations=2
)
critic_result = orchestrator._normalize_critic_scores(critic_result)
if settings.quality_refiner_enabled:
quality_checks = await orchestrator._run_quality_checks(refined_post, example_post_texts)
grammar_errors = quality_checks['grammar_check'].get('error_count', 0)
style_similarity = quality_checks['style_check'].get('avg_similarity', 1.0)
readability_passed = quality_checks['readability_check'].get('passed', True)
needs_polish = (
grammar_errors > 0 or
style_similarity < 0.75 or
not readability_passed
)
if needs_polish:
refined_post = await orchestrator.quality_refiner.final_polish(
post=refined_post,
quality_checks=quality_checks,
profile_analysis=full_analysis,
example_posts=example_post_texts
)
refined_post = sanitize_post_content(refined_post)
return JSONResponse({
"success": True,
"post": refined_post,
@@ -4815,15 +4949,22 @@ async def company_chat_generate_post(request: Request):
topic = {"title": message[:100], "fact": message, "relevance": "Company-created content"}
strategy_weight = orchestrator._get_effective_strategy_weight(
base_weight=post_type.strategy_weight,
post_type=post_type,
post_type_analysis=post_type.analysis if post_type else None
)
plan = await orchestrator.generate_post_plan(
topic=topic,
profile_analysis=profile_analysis.full_analysis,
company_strategy=company_strategy,
strategy_weight=getattr(post_type, 'strategy_weight', 0.5),
user_thoughts=message
strategy_weight=strategy_weight,
user_thoughts=message,
post_type_analysis=post_type.analysis if post_type and post_type.analysis else None
)
if plan:
topic["post_plan"] = plan
topic["content_plan"] = plan
post_content = await writer.process(
topic=topic,
profile_analysis=profile_analysis.full_analysis,
@@ -4831,10 +4972,53 @@ async def company_chat_generate_post(request: Request):
post_type=post_type,
user_thoughts=message,
company_strategy=company_strategy,
strategy_weight=post_type.strategy_weight
strategy_weight=strategy_weight
)
post_content = sanitize_post_content(post_content)
# Run critic + one revision pass for chat flow quality parity
critic_result = await orchestrator.critic.process(
post=post_content,
profile_analysis=profile_analysis.full_analysis,
topic=topic,
example_posts=example_post_texts,
iteration=1,
max_iterations=2
)
if not critic_result.get("approved", False):
post_content = await writer.process(
topic=topic,
profile_analysis=profile_analysis.full_analysis,
feedback=critic_result.get("feedback", ""),
previous_version=post_content,
example_posts=example_post_texts,
critic_result=critic_result,
post_type=post_type,
user_thoughts=message,
company_strategy=company_strategy,
strategy_weight=strategy_weight
)
post_content = sanitize_post_content(post_content)
if settings.quality_refiner_enabled:
quality_checks = await orchestrator._run_quality_checks(post_content, example_post_texts)
grammar_errors = quality_checks['grammar_check'].get('error_count', 0)
style_similarity = quality_checks['style_check'].get('avg_similarity', 1.0)
readability_passed = quality_checks['readability_check'].get('passed', True)
needs_polish = (
grammar_errors > 0 or
style_similarity < 0.75 or
not readability_passed
)
if needs_polish:
post_content = await orchestrator.quality_refiner.final_polish(
post=post_content,
quality_checks=quality_checks,
profile_analysis=profile_analysis.full_analysis,
example_posts=example_post_texts
)
post_content = sanitize_post_content(post_content)
return JSONResponse({
"success": True,
"post": post_content,