- 排除 .env / *.bak / 内部运维文档(README_INTERNAL.html) - config.py 默认密码已替换为占位符 CHANGE_ME_* - init_db.sql 移除生产数据库用户 GRANT 段 - README.html 数据库用户名已脱敏 - 保留:源码 + 公网 API 文档 + 建表 SQL(无授权语句)
81 lines
3.1 KiB
Python
81 lines
3.1 KiB
Python
"""Persona Generator - Generate user persona from scenarios and memories."""
|
|
import json
|
|
import logging
|
|
from typing import Optional
|
|
|
|
from lifecycle.llm_parse import parse_llm_json_object
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
PERSONA_SYSTEM_PROMPT = """你是JSON生成器。直接输出JSON对象,禁止分析、思考、解释、markdown。
|
|
|
|
根据记忆和场景生成用户画像。
|
|
|
|
输出格式(第一个字符必须是{,最后一个字符必须是}):
|
|
{"preferences":["偏好1"],"habits":["习惯1"],"expertise":["擅长1"],"communication_style":"风格","summary":"100字以内摘要"}
|
|
|
|
只输出JSON,不要有任何其他文字。"""
|
|
|
|
|
|
class PersonaGenerator:
|
|
"""Generate user persona from memories and scenarios."""
|
|
|
|
def __init__(self, mysql_store, llm_client):
|
|
self.mysql = mysql_store
|
|
self.llm = llm_client
|
|
|
|
def generate(self, agent_id: str, team_id: str,
|
|
max_items: int = 30) -> dict:
|
|
if not self.llm.available:
|
|
return {"error": "LLM not configured. Set LLM_API_URL, LLM_API_KEY, LLM_MODEL environment variables."}
|
|
|
|
memories = self.mysql.get_personal_memories_by_agent(agent_id, limit=max_items)
|
|
scenarios = self.mysql.get_scenarios_by_agent(agent_id)
|
|
|
|
if not memories and not scenarios:
|
|
return {"error": "No memories or scenarios found for this agent"}
|
|
|
|
context_parts = []
|
|
if memories:
|
|
mem_lines = [f"- {m.get('content', '')[:100]}" for m in memories]
|
|
context_parts.append("历史记忆:\n" + "\n".join(mem_lines))
|
|
if scenarios:
|
|
scene_lines = [f"- [{s.get('name', '')}] {s.get('summary', '')}" for s in scenarios]
|
|
context_parts.append("已识别场景:\n" + "\n".join(scene_lines))
|
|
|
|
user_prompt = "请根据以下内容生成用户画像JSON:\n\n" + "\n\n".join(context_parts)
|
|
|
|
try:
|
|
persona = parse_llm_json_object(
|
|
self.llm, PERSONA_SYSTEM_PROMPT, user_prompt,
|
|
temperature=0.3, context="generate-persona",
|
|
max_tokens=2000,
|
|
)
|
|
except ValueError as e:
|
|
return {"error": str(e)}
|
|
|
|
if not isinstance(persona, dict):
|
|
logger.warning("LLM returned non-dict persona: %r", persona)
|
|
return {"error": "LLM returned invalid persona format"}
|
|
|
|
pid = self.mysql.add_persona(
|
|
team_id=team_id,
|
|
agent_id=agent_id,
|
|
preferences=persona.get("preferences", []),
|
|
habits=persona.get("habits", []),
|
|
expertise=persona.get("expertise", []),
|
|
communication_style=persona.get("communication_style", ""),
|
|
summary=persona.get("summary", ""),
|
|
)
|
|
persona["id"] = pid
|
|
return {"persona": persona}
|
|
|
|
def get_persona(self, agent_id: str):
|
|
return self.mysql.get_persona_by_agent(agent_id)
|
|
|
|
def delete_persona(self, persona_id: str, team_id: str) -> bool:
|
|
persona = self.mysql.get_persona(persona_id)
|
|
if not persona or persona["team_id"] != team_id:
|
|
return False
|
|
return self.mysql.delete_persona(persona_id)
|