standard_eval.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import json
  2. import os
  3. import sys
  4. from datetime import datetime
  5. from typing import List, Dict, Any
  6. # Ensure project root is in python path
  7. sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
  8. from sqlalchemy.orm import Session
  9. from app.db.session import SessionLocal
  10. from app.models import Forum, Message
  11. from app.crud import get_forum
  12. from app.agent.agent import run_simple_agent
  13. # Define the 5 Evaluation Dimensions (Optimized for Multi-Agent Advantages)
  14. EVALUATION_METRICS = {
  15. "1. 观点多样性与碰撞 (Perspective Diversity & Collision)": {
  16. "definition": "是否涵盖议题的多个对立面或不同维度,存在鲜明的观点碰撞和张力。",
  17. "score_1": "观点单一,老生常谈,缺乏新意或对立视角。",
  18. "score_5": "涵盖多学科/多立场视角,存在深度的观点交锋和辩论。",
  19. "optimization": "引入背景、立场各异的角色,鼓励辩论。"
  20. },
  21. "2. 深度演进 (Depth Evolution)": {
  22. "definition": "随着对话进行,观点是否变得更加深刻,是否解决了初步的质疑,实现螺旋上升。",
  23. "score_1": "观点在原地打转,只是换个说法重复。",
  24. "score_5": "像剥洋葱一样层层递进,从表面现象深入到本质机制或哲学层面。",
  25. "optimization": "引入定期总结和深度思考机制,防止循环论证。"
  26. },
  27. "3. 交互批判性 (Interactive Criticality)": {
  28. "definition": "对他人观点的回应是否具有批判性,能否精准指出逻辑漏洞并迫使对方回应。",
  29. "score_1": "自说自话,或只是简单的附和/反对,无逻辑支撑。",
  30. "score_5": "精准打击对方逻辑弱点,迫使对方修正或完善观点,形成有效对话。",
  31. "optimization": "共享记忆机制,确保智能体能准确引用和反驳。"
  32. },
  33. "4. 观点实质性与落地性 (Argument Substantiality & Grounding)": {
  34. "definition": "发言是否具备实质内容,引用具体案例、数据或历史事实,拒绝“假大空”。",
  35. "score_1": "充斥正确的废话、盲目附和,缺乏细节支撑。",
  36. "score_5": "论据详实,引用具体数据、文献或案例支撑论点,逻辑严密。",
  37. "optimization": "接入外部知识库(RAG)或专家角色设定。"
  38. },
  39. "5. 角色鲜明度 (Character Distinctiveness)": {
  40. "definition": "角色是否具有独特的人格魅力和语言风格,而非千篇一律的AI味。",
  41. "score_1": "所有角色说话都像同一个AI助手,千人一面。",
  42. "score_5": "即使遮住名字,也能通过语言风格和思维方式分辨出是谁。",
  43. "optimization": "ReAct动态生成的高自由度角色,强化人设指令。"
  44. }
  45. }
  46. def get_forum_history(db: Session, forum_id: int) -> str:
  47. """Fetch and format forum history for evaluation."""
  48. forum = get_forum(db, forum_id)
  49. if not forum:
  50. print(f"Forum {forum_id} not found.")
  51. return ""
  52. messages = db.query(Message).filter(Message.forum_id == forum_id).order_by(Message.timestamp.asc()).all()
  53. history_str = f"Forum Topic: {forum.topic}\n\n"
  54. for msg in messages:
  55. history_str += f"[{msg.speaker_name}]: {msg.content}\n"
  56. return history_str
  57. def evaluate_forum(forum_id: int):
  58. """Run standard evaluation for a single forum."""
  59. db = SessionLocal()
  60. try:
  61. history = get_forum_history(db, forum_id)
  62. if not history:
  63. return
  64. print(f"Evaluating Forum {forum_id}...")
  65. prompt = f"""
  66. 你是一位公正、专业的辩论与讨论评估专家。请根据以下圆桌论坛的对话记录,严格按照给定的 5 个维度进行评分和点评。
  67. 【对话记录】
  68. {history[:10000]} # Truncate if too long, or handle splitting
  69. 【评估维度】
  70. """
  71. for dim, criteria in EVALUATION_METRICS.items():
  72. prompt += f"\n### {dim}\n"
  73. prompt += f"- 核心定义: {criteria['definition']}\n"
  74. prompt += f"- 1分标准: {criteria['score_1']}\n"
  75. prompt += f"- 5分标准: {criteria['score_5']}\n"
  76. prompt += f"- 参考优化方向: {criteria['optimization']}\n"
  77. prompt += """
  78. \n【输出格式要求】
  79. 请直接输出一个 JSON 对象,不要包含 Markdown 格式(如 ```json)。格式如下:
  80. {
  81. "scores": {
  82. "topic_adherence": 0,
  83. "argument_substantiality": 0,
  84. "boundary_control": 0,
  85. "contextual_coherence": 0,
  86. "role_consistency": 0
  87. },
  88. "comments": {
  89. "topic_adherence": "点评...",
  90. "argument_substantiality": "点评...",
  91. "boundary_control": "点评...",
  92. "contextual_coherence": "点评...",
  93. "role_consistency": "点评..."
  94. },
  95. "overall_summary": "整体评价..."
  96. }
  97. """
  98. result_text = run_simple_agent(
  99. "ForumEvaluationAgent",
  100. "你是一位公正、专业的多智能体讨论评估专家,只返回要求的 JSON。",
  101. prompt,
  102. )
  103. if result_text:
  104. # Clean up markdown if present
  105. if "```json" in result_text:
  106. result_text = result_text.split("```json")[1].split("```")[0]
  107. elif "```" in result_text:
  108. result_text = result_text.split("```")[1].split("```")[0]
  109. try:
  110. result = json.loads(result_text)
  111. # Save result
  112. os.makedirs("exam/results", exist_ok=True)
  113. output_file = f"exam/results/eval_forum_{forum_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
  114. with open(output_file, "w", encoding="utf-8") as f:
  115. json.dump(result, f, ensure_ascii=False, indent=2)
  116. print(f"Evaluation complete. Results saved to {output_file}")
  117. print(json.dumps(result, ensure_ascii=False, indent=2))
  118. except json.JSONDecodeError:
  119. print("Failed to parse LLM response as JSON.")
  120. print("Raw response:", result_text)
  121. else:
  122. print("HelloAgents evaluation failed.")
  123. finally:
  124. db.close()
  125. if __name__ == "__main__":
  126. if len(sys.argv) < 2:
  127. print("Usage: python exam/standard_eval.py <forum_id>")
  128. else:
  129. evaluate_forum(int(sys.argv[1]))