from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import PromptTemplate from app.llm import llm general_prompt = """ 你是一个专业的文本改写助手。请分析输入文本,按以下规则处理: **规则:** 1. 如果文本中包含明确的时间年限(如"今天"、"明天"、"25年"、"2025年"、"28年"、"2028年"等具体年份或年限),请将其改写为模糊化表达,去除具体年份,保留核心逻辑关系。 2. 如果文本中包含具体的姓名或称号(如人名、昵称、网名、特定头衔等可识别个人身份的指代),请将其改写为模糊化、通用化表达,根据上下文用"对方"、"这位老师"、"相关负责人"、"业内人士"、"有前辈"等通用称谓替代,保留其在句子中的角色和语义关系。 3. 如果文本中**既不包含**明确的时间年限,**也不包含**任何具体的姓名或称号,则**保持原样返回**,不做任何修改。 4. 改写时保留原文的核心语义:毕业时间、校招条件限制、社招要求、AI岗位趋势、竞争压力、简历包装等关键信息。 5. 去除具体时间数字,用"毕业后X年"、"校招年限要求"、"当前"等相对化表达替代;去除具体姓名称号,用不指向特定个人的通用化称谓替代。 6. 保持原文字数大致相当,不要过度扩写或删减。 **示例一(时间模糊化):** 输入:"如果25年毕业,校招机会基本没有了,因为25年毕业的学生在28年已经不符合校招条件,只能走社招。社招通常要求至少一年工作经验,且今年AI校招的美术岗位在大量减少,竞争只会更大。学得很好也需要包装简历走社招,和社保没有直接关系。" 输出:"如果刚毕业不久,校招机会基本没有了,因为毕业一段时间后已经不符合校招年限条件,只能走社招。社招通常要求至少一年工作经验,且当前AI校招的美术岗位在大量减少,竞争只会更大。学得很好也需要包装简历走社招,和社保没有直接关系。" **示例二(时间与姓名称号同时模糊化):** 输入:"王工之前提醒过,25届的同学最迟26年就要准备转社招,再拖下去机会更少。" 输出:"有前辈之前提醒过,刚毕业的同学最迟毕业一两年内就要准备转社招,再拖下去机会更少。" **请直接输出处理后的文本,不要解释,不要添加额外内容。** 输入文本:{text} """ general_merge_prompt = """ # 任务 从三类输入中提取与"下一次回复"直接相关的结构化关键要点,按优先级融合后输出。 # 输入 - 最新聊天内容(最高优先级): {message} - 历史相关知识: {milvus_content} - 标准内容: {standard} # 处理规则 1. 【优先级去重】同一事实优先采用 {message},缺失部分依次补充 {milvus_content}、{standard},不重复罗列。 2. 【个人信息脱敏】删除所有个人身份信息(姓名、年级、专业全称、学校、联系方式等)。 - ⚠️ 特别注意:「回复主题」同样需要脱敏,不得包含具体专业、年级、姓名等身份标识。主题应概括"咨询类型/事项",而非"用户身份"。 3. 【用户事实过滤】严格去除所有与用户主体相关的客观事实信息,包括但不限于: - 用户的计划、意向、时间安排、人数规模、行程动向; - 用户当前的状态、情绪、顾虑、已做出的决定; - 用户提及的任何"我/我们"视角的行为描述。 仅保留销售/服务方需要执行的动作、接待安排、标准流程、适用条件与门槛。 4. 【主题相关性过滤】严格过滤与当前回复主题无关的历史信息,包括但不限于: - 已明确终止的咨询记录(如用户已拒绝并结束的话题); - 与当前课程方向无关的其他技术栈/工具争议; - 负面情绪或人际冲突类描述(如"互删""不考虑"等)。 仅保留对当前回复有指导价值的事实要点。 5. 【纯事实提取】只提取客观事实要点,不生成完整回复,不添加销售话术、过渡句或主观推测。 6. 【空值处理】若无核心数字或适用条件,对应字段输出为空列表 `[]` 或留空,不编造。 # 输出格式 严格按以下 YAML 输出,禁止添加额外解释: ```yaml 回复主题: 关键信息点: - 信息: 核心数字: - 适用条件/门槛: - """ class TextExtract: async def text_extract(self, text:str)->str: if not text: return "" prompt_template = PromptTemplate(template=general_prompt, input_variables=["text"]) str_output_parser = StrOutputParser() chain = prompt_template | llm |str_output_parser answer = await chain.ainvoke({"text": text}) return answer async def message_extract(self, message:str, milvus_content:str, standard:str)->str: prompt_template = PromptTemplate(template=general_merge_prompt, input_variables=["message", "milvus_content", "standard"]) str_output_parser = StrOutputParser() chain = prompt_template | llm |str_output_parser answer = await chain.ainvoke({"message": message, "milvus_content": milvus_content, "standard": standard}) return answer