"""
智能体服务
"""
import logging
import time
from typing import Any, Dict, List, Optional

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from ai_platform.models import (
    Agent, AgentConversation, AgentMessage, LLMModel,
)
from .llm_service import LLMService

logger = logging.getLogger(__name__)


class AgentService:
    """
    智能体服务
    
    管理智能体的对话和推理
    """
    
    def __init__(self, db: Optional[AsyncSession] = None):
        self._db = db
        self.llm_service = LLMService(db)
    
    async def chat(
        self,
        agent: Agent,
        conversation: AgentConversation,
        user_message: str,
        application_id: str = None,
        form_code: str = None,
        attachments: List[Dict] = None,
    ):
        """
        与智能体对话（流式）
        
        Args:
            agent: 智能体
            conversation: 对话
            user_message: 用户消息
            application_id: 子应用 ID（用于表单创建等场景）
            form_code: 表单编码（从表单列表调用时传入）
            attachments: 附件列表 [{id, type, name, url, mime_type, size}]
            
        Yields:
            事件流
        """
        if agent.mode == 'autonomous':
            async for event in self._chat_autonomous(agent, conversation, user_message, attachments):
                yield event
        elif agent.mode == 'dialog_flow':
            async for event in self._chat_dialog_flow(agent, conversation, user_message, application_id, form_code, attachments):
                yield event
        else:
            yield {'type': 'error', 'content': f'不支持的模式: {agent.mode}'}
    
    async def _chat_autonomous(
        self,
        agent: Agent,
        conversation: AgentConversation,
        user_message: str,
        attachments: List[Dict] = None,
    ):
        """
        自主规划模式对话
        
        优先使用原生 Function Calling，如果模型不支持则回退到 ReAct 模式
        
        Yields:
            流式事件
        """
        # 检查模型是否支持 Function Calling
        supports_function_call = await self._check_model_supports_function_call(agent.model_id)
        
        if supports_function_call:
            async for event in self._chat_autonomous_function_calling(agent, conversation, user_message, attachments):
                yield event
        else:
            async for event in self._chat_autonomous_react(agent, conversation, user_message, attachments):
                yield event
    
    async def _check_model_supports_function_call(self, model_id) -> bool:
        """检查模型是否支持 Function Calling"""
        if not self._db or not model_id:
            return False
        
        result = await self._db.execute(
            select(LLMModel).where(LLMModel.id == model_id, LLMModel.is_deleted == False)
        )
        model = result.scalar_one_or_none()
        return model.supports_function_call if model else False
    
    async def _chat_autonomous_function_calling(
        self,
        agent: Agent,
        conversation: AgentConversation,
        user_message: str,
        attachments: List[Dict] = None,
    ):
        """
        自主规划模式对话（支持多模态附件）
        
        Yields:
            流式事件
        """
        from ai_platform.providers.base import LLMMessage
        
        start_time = time.time()
        
        if not self._db:
            yield {'type': 'error', 'content': '数据库会话未初始化'}
            return
        
        # 创建用户消息（包含附件）
        # 附件格式: [{file_id, type, name, mime_type, size}]
        stored_attachments = []
        if attachments:
            for att in attachments:
                stored_attachments.append({
                    'file_id': att.get('file_id'),
                    'type': att.get('type', 'file'),
                    'name': att.get('name', ''),
                    'mime_type': att.get('mime_type', ''),
                    'size': att.get('size', 0),
                })
        
        user_msg = AgentMessage(
            conversation_id=conversation.id,
            role='user',
            content=user_message,
            attachments=stored_attachments,
            status='completed',
        )
        self._db.add(user_msg)
        await self._db.flush()
        
        # 创建助手消息（pending 状态）
        assistant_msg = AgentMessage(
            conversation_id=conversation.id,
            role='assistant',
            content='',
            status='pending',
        )
        self._db.add(assistant_msg)
        await self._db.flush()
        
        yield {
            'type': 'start',
            'conversation_id': str(conversation.id),
            'message_id': str(assistant_msg.id),
        }
        
        try:
            # 构建系统提示词
            system_prompt = self._build_system_prompt_simple(agent)
            
            # 标注直接回复检查（高相似度时跳过 LLM，直接返回标注答案）
            annotation_reply = await self._check_annotation_direct_reply(agent, user_message)
            if annotation_reply:
                final_answer = annotation_reply['answer']
                elapsed_time = int((time.time() - start_time) * 1000)
                assistant_msg.content = final_answer
                assistant_msg.status = 'completed'
                assistant_msg.elapsed_time = elapsed_time
                
                yield {
                    'type': 'annotation_reply',
                    'content': f"标注直接回复 (相似度: {annotation_reply['score']:.2f})",
                }
                yield {
                    'type': 'answer',
                    'content': final_answer,
                }
                
                conversation.message_count = (conversation.message_count or 0) + 2
                if conversation.message_count == 2 and (not conversation.title or conversation.title == "新建对话"):
                    self._generate_title(conversation, user_message)
                agent.message_count = (agent.message_count or 0) + 2
                await self._db.commit()
                
                yield {
                    'type': 'complete',
                    'message_id': str(assistant_msg.id),
                    'conversation_id': str(conversation.id),
                    'tokens_used': 0,
                    'elapsed_time': elapsed_time,
                }
                return
            
            # 知识库检索增强（RAG）
            knowledge_context = await self._retrieve_knowledge_context(agent, user_message)
            if knowledge_context:
                system_prompt = self._inject_knowledge_context(system_prompt, knowledge_context)
                yield {
                    'type': 'knowledge_retrieval',
                    'content': knowledge_context['summary'],
                    'result_count': knowledge_context['result_count'],
                }
            
            # 获取对话历史
            history = await self._get_conversation_history(conversation, limit=10)
            
            # 构建当前用户消息内容（支持多模态）
            user_content = LLMMessage.create_multimodal_content(user_message, attachments)
            history.append({'role': 'user', 'content': user_content})
            
            # 构建消息
            messages = [{'role': 'system', 'content': system_prompt}] + history
            
            # 检查是否启用流式输出
            enable_streaming = getattr(agent, 'enable_streaming', True)
            
            total_tokens = 0
            final_answer = ''
            
            if enable_streaming:
                # 流式输出
                accumulated_content = ''
                async for chunk in self.llm_service.chat_stream(
                    model_id=str(agent.model_id),
                    messages=messages,
                    temperature=agent.temperature or 0.7,
                    max_tokens=agent.max_tokens or 2048,
                ):
                    if chunk.content:
                        accumulated_content += chunk.content
                        yield {
                            'type': 'llm_chunk',
                            'content': chunk.content,
                            'accumulated_content': accumulated_content,
                        }
                    
                    if chunk.is_finished:
                        total_tokens = chunk.total_tokens
                        final_answer = accumulated_content
            else:
                # 非流式输出
                response = await self.llm_service.chat_async(
                    model_id=str(agent.model_id),
                    messages=messages,
                    temperature=agent.temperature or 0.7,
                    max_tokens=agent.max_tokens or 2048,
                )
                
                total_tokens = response.total_tokens
                final_answer = response.content
                
                yield {
                    'type': 'answer',
                    'content': final_answer,
                }
            
            # 更新助手消息
            elapsed_time = int((time.time() - start_time) * 1000)
            assistant_msg.content = final_answer
            assistant_msg.status = 'completed'
            assistant_msg.total_tokens = total_tokens
            assistant_msg.elapsed_time = elapsed_time
            
            # 更新对话统计
            conversation.message_count = (conversation.message_count or 0) + 2
            conversation.total_tokens = (conversation.total_tokens or 0) + total_tokens
            
            # 自动生成标题（第一次对话时，且标题为默认值）
            if conversation.message_count == 2 and (not conversation.title or conversation.title == "新建对话"):
                self._generate_title(conversation, user_message)
            
            # 更新智能体统计
            agent.message_count = (agent.message_count or 0) + 2
            agent.total_tokens = (agent.total_tokens or 0) + total_tokens
            
            await self._db.commit()
            
            yield {
                'type': 'complete',
                'message_id': str(assistant_msg.id),
                'conversation_id': str(conversation.id),
                'tokens_used': total_tokens,
                'elapsed_time': elapsed_time,
            }
            
        except Exception as e:
            logger.exception(f'Agent chat error: {e}')
            assistant_msg.status = 'failed'
            assistant_msg.error_message = str(e)
            await self._db.commit()
            yield {
                'type': 'error',
                'content': str(e),
            }
    
    async def _chat_autonomous_react(
        self,
        agent: Agent,
        conversation: AgentConversation,
        user_message: str,
        attachments: List[Dict] = None,
    ):
        """
        ReAct 模式（简化版，不使用工具，直接复用 function calling 逻辑）
        
        Yields:
            流式事件
        """
        # 直接复用简化后的 function calling 逻辑
        async for event in self._chat_autonomous_function_calling(agent, conversation, user_message, attachments):
            yield event
    
    async def _chat_dialog_flow(
        self,
        agent: Agent,
        conversation: AgentConversation,
        user_message: str,
        application_id: str = None,
        form_code: str = None,
        attachments: List[Dict] = None,
    ):
        """
        对话流模式对话
        
        直接复用工作流服务的执行逻辑，透传工作流事件
        
        Args:
            agent: 智能体
            conversation: 对话
            user_message: 用户消息
            application_id: 子应用 ID（用于表单创建等场景）
            form_code: 表单编码（从表单列表调用时传入）
            attachments: 附件列表
            
        Yields:
            流式事件
        """
        start_time = time.time()
        
        if not self._db:
            yield {'type': 'error', 'content': '数据库会话未初始化'}
            return
        
        # 创建用户消息（包含附件）
        # 附件格式: [{file_id, type, name, mime_type, size}]
        stored_attachments = []
        if attachments:
            for att in attachments:
                stored_attachments.append({
                    'file_id': att.get('file_id'),
                    'type': att.get('type', 'file'),
                    'name': att.get('name', ''),
                    'mime_type': att.get('mime_type', ''),
                    'size': att.get('size', 0),
                })
        
        user_msg = AgentMessage(
            conversation_id=conversation.id,
            role='user',
            content=user_message,
            attachments=stored_attachments,
            status='completed',
        )
        self._db.add(user_msg)
        await self._db.flush()
        
        # 创建助手消息
        assistant_msg = AgentMessage(
            conversation_id=conversation.id,
            role='assistant',
            content='',
            status='pending',
        )
        self._db.add(assistant_msg)
        await self._db.flush()
        
        yield {
            'type': 'start',
            'conversation_id': str(conversation.id),
            'message_id': str(assistant_msg.id),
        }
        
        try:
            from ai_platform.services.workflow_service import AIWorkflowService
            
            workflow_service = AIWorkflowService(self._db)
            
            # 检查是否有进行中的工作流运行
            workflow_run_id = None
            if conversation.extra_data:
                workflow_run_id = conversation.extra_data.get('workflow_run_id')
            
            final_content = ''
            is_waiting = False
            total_tokens = 0
            current_run_id = workflow_run_id
            
            # 获取对话历史（如果启用了记忆功能）
            conversation_history = []
            if agent.enable_memory:
                conversation_history = await self._get_conversation_history(
                    conversation, 
                    limit=agent.memory_window or 10
                )
            
            if workflow_run_id:
                # 恢复工作流执行 - 使用异步方法
                # 将附件内容（文件解析内容或图片OCR）整合到 user_input 中
                enhanced_user_input = user_message
                if attachments:
                    attachment_texts = []
                    for att in attachments:
                        text_content = att.get('text_content', '')
                        if text_content:
                            file_name = att.get('name', 'unknown')
                            attachment_texts.append(f"\n[附件: {file_name}]\n{text_content}")
                    
                    if attachment_texts:
                        enhanced_user_input = user_message + '\n' + '\n'.join(attachment_texts)
                
                async for event in workflow_service.resume_workflow_stream_async(
                    run_id=workflow_run_id,
                    user_input=enhanced_user_input,
                    conversation_history=conversation_history,
                ):
                    event_type = event.get('type')
                    
                    if event_type == 'answer':
                        final_content = event.get('content', '')
                    elif event_type == 'llm_chunk':
                        accumulated = event.get('accumulated_content', '')
                        if accumulated:
                            final_content = accumulated
                    elif event_type == 'node_complete':
                        node_type = event.get('node_type')
                        if node_type == 'llm':
                            outputs = event.get('outputs', {})
                            output = outputs.get('output', '')
                            if output:
                                final_content = output
                    elif event_type == 'waiting_input':
                        is_waiting = True
                    elif event_type == 'complete':
                        total_tokens = event.get('total_tokens', 0)
                    
                    yield event
            else:
                # 新对话，启动工作流 - 使用异步方法
                if not agent.workflow_id:
                    yield {'type': 'error', 'content': '智能体未配置工作流'}
                    return
                
                # 构建工作流输入变量
                # 将附件内容（文件解析内容或图片OCR）整合到 user_input 中
                enhanced_user_input = user_message
                if attachments:
                    attachment_texts = []
                    for att in attachments:
                        text_content = att.get('text_content', '')
                        if text_content:
                            file_name = att.get('name', 'unknown')
                            attachment_texts.append(f"\n[附件: {file_name}]\n{text_content}")
                    
                    if attachment_texts:
                        enhanced_user_input = user_message + '\n' + '\n'.join(attachment_texts)
                
                workflow_inputs = {'user_input': enhanced_user_input}
                if application_id:
                    workflow_inputs['application_id'] = application_id
                if form_code:
                    workflow_inputs['form_code'] = form_code
                
                # 调试日志
                import logging
                logger = logging.getLogger(__name__)
                logger.info(f"[AgentService] form_code parameter: {form_code}")
                logger.info(f"[AgentService] workflow_inputs: {workflow_inputs}")
                
                async for event in workflow_service.run_workflow_stream_async(
                    workflow_id=str(agent.workflow_id),
                    inputs=workflow_inputs,
                    conversation_id=str(conversation.id),
                    conversation_history=conversation_history,
                    trigger_type='agent',
                ):
                    event_type = event.get('type')
                    
                    if event_type == 'start':
                        current_run_id = event.get('run_id')
                    elif event_type == 'answer':
                        final_content = event.get('content', '')
                    elif event_type == 'llm_chunk':
                        accumulated = event.get('accumulated_content', '')
                        if accumulated:
                            final_content = accumulated
                    elif event_type == 'node_complete':
                        node_type = event.get('node_type')
                        if node_type == 'llm':
                            outputs = event.get('outputs', {})
                            output = outputs.get('output', '')
                            if output:
                                final_content = output
                    elif event_type == 'waiting_input':
                        is_waiting = True
                        # 保存工作流运行 ID 到对话元数据
                        if current_run_id:
                            conversation.extra_data = conversation.extra_data or {}
                            conversation.extra_data['workflow_run_id'] = current_run_id
                    elif event_type == 'complete':
                        total_tokens = event.get('total_tokens', 0)
                    
                    yield event
            
            # 更新助手消息
            elapsed_time = int((time.time() - start_time) * 1000)
            
            if final_content:
                assistant_msg.content = final_content
            
            assistant_msg.status = 'completed'
            assistant_msg.elapsed_time = elapsed_time
            assistant_msg.total_tokens = total_tokens
            
            # 更新对话统计
            conversation.message_count = (conversation.message_count or 0) + 2
            conversation.total_tokens = (conversation.total_tokens or 0) + total_tokens
            
            # 自动生成标题（第一次对话时，且标题为默认值）
            if conversation.message_count == 2 and (not conversation.title or conversation.title == "新建对话"):
                self._generate_title(conversation, user_message)
            
            # 如果工作流完成（非等待状态），清除对话元数据
            if not is_waiting:
                if conversation.extra_data:
                    conversation.extra_data.pop('workflow_run_id', None)
            
            await self._db.commit()
            
            yield {
                'type': 'complete',
                'elapsed_time': elapsed_time,
                'tokens_used': total_tokens,
            }
            
        except Exception as e:
            logger.exception(f'Dialog flow error: {e}')
            assistant_msg.status = 'failed'
            assistant_msg.error_message = str(e)
            await self._db.commit()
            yield {
                'type': 'error',
                'content': str(e),
            }
    
    def _build_system_prompt_simple(self, agent: Agent) -> str:
        """构建简化的系统提示词"""
        # 基础提示词
        base_prompt = agent.system_prompt
        
        # 如果没有系统提示词，从人设生成
        if not base_prompt and agent.persona:
            base_prompt = self._generate_prompt_from_persona(agent.persona)
        
        if not base_prompt:
            base_prompt = "你是一个智能助手，可以帮助用户完成各种任务。回答要简洁明了，使用中文。"
        
        return base_prompt
    
    def _generate_prompt_from_persona(self, persona: Dict[str, Any]) -> str:
        """从人设配置生成提示词"""
        parts = []
        
        if persona.get('role'):
            parts.append(persona['role'])
        
        if persona.get('personality'):
            personalities = persona['personality']
            if isinstance(personalities, list):
                parts.append(f"你的性格特点是：{', '.join(personalities)}。")
        
        if persona.get('skills'):
            skills = persona['skills']
            if isinstance(skills, list):
                parts.append(f"你擅长：{', '.join(skills)}。")
        
        if persona.get('background'):
            parts.append(persona['background'])
        
        if persona.get('constraints'):
            constraints = persona['constraints']
            if isinstance(constraints, list):
                parts.append("注意事项：\n" + "\n".join(f"- {c}" for c in constraints))
        
        return "\n\n".join(parts)
    
    async def _get_conversation_history(
        self,
        conversation: AgentConversation,
        limit: int = 10,
    ) -> List[Dict[str, str]]:
        """获取对话历史"""
        if not self._db:
            return []
        
        result = await self._db.execute(
            select(AgentMessage).where(
                AgentMessage.conversation_id == conversation.id,
                AgentMessage.is_deleted == False,
                AgentMessage.role.in_(['user', 'assistant']),
                AgentMessage.status == 'completed'
            ).order_by(AgentMessage.sys_create_datetime.desc()).limit(limit)
        )
        messages = result.scalars().all()
        
        history = []
        for msg in reversed(list(messages)):
            history.append({
                'role': msg.role,
                'content': msg.content,
            })
        
        return history
    
    def _generate_title(self, conversation, first_message: str):
        """自动生成对话标题"""
        # 简单截取前 20 个字符作为标题
        title = first_message[:20]
        if len(first_message) > 20:
            title += '...'
        conversation.title = title

    async def _check_annotation_direct_reply(
        self,
        agent: Agent,
        query: str,
    ) -> Optional[Dict[str, Any]]:
        """
        检查标注直接回复（Dify 风格）
        
        当启用标注回复且匹配到高相似度标注时，直接返回标注答案，跳过 LLM 调用。
        
        Returns:
            {'answer': str, 'score': float, 'question': str} 或 None
        """
        knowledge_base_ids = getattr(agent, 'knowledge_base_ids', None) or []
        if not knowledge_base_ids or not self._db:
            return None

        knowledge_config = getattr(agent, 'knowledge_config', None) or {}
        annotation_reply_enabled = knowledge_config.get('annotation_reply_enabled', False)
        if not annotation_reply_enabled:
            return None

        annotation_threshold = knowledge_config.get('annotation_threshold', 0.9)

        try:
            from ai_platform.knowledge.services.retrieval_service import RetrievalService
            from ai_platform.knowledge.models import KnowledgeBase
            from sqlalchemy import select

            # 获取第一个知识库的 embedding 配置
            kb_result = await self._db.execute(
                select(KnowledgeBase).where(
                    KnowledgeBase.id.in_(knowledge_base_ids),
                    KnowledgeBase.is_deleted == False,
                )
            )
            first_kb = kb_result.scalars().first()
            if not first_kb or not first_kb.embedding_model_id:
                return None

            service = RetrievalService(self._db)
            annotation_results = await service._match_annotations(
                query=query,
                knowledge_base_ids=knowledge_base_ids,
                embedding_model_id=first_kb.embedding_model_id,
                score_threshold=annotation_threshold,
                dimensions=first_kb.embedding_dimensions,
                max_results=1,
            )

            if annotation_results:
                best = annotation_results[0]
                metadata = getattr(best, 'metadata', {}) or {}
                logger.info(
                    f'标注直接回复命中: score={best.score}, '
                    f'question={metadata.get("question", "")}, answer={best.content[:50]}'
                )

                # 记录检索日志
                try:
                    from ai_platform.knowledge.models import KnowledgeRetrievalLog
                    log = KnowledgeRetrievalLog(
                        query=query,
                        knowledge_base_ids=knowledge_base_ids,
                        retrieval_mode='annotation',
                        top_k=1,
                        score_threshold=annotation_threshold,
                        result_count=1,
                        results=[{'segment_id': best.segment_id, 'score': best.score, 'kb_id': best.knowledge_base_id}],
                        rerank_applied='false',
                        elapsed_time=0,
                        source='agent_annotation',
                    )
                    self._db.add(log)
                    await self._db.flush()
                except Exception as e:
                    logger.warning(f'记录标注回复日志失败: {e}')

                return {
                    'answer': best.content,
                    'score': best.score,
                    'question': metadata.get('question', ''),
                }

        except Exception as e:
            logger.warning(f'标注直接回复检查失败: {e}')

        return None

    async def _retrieve_knowledge_context(
        self,
        agent: Agent,
        query: str,
    ) -> Optional[Dict[str, Any]]:
        """
        检索知识库上下文（RAG）
        
        Args:
            agent: 智能体（包含 knowledge_base_ids 和 knowledge_config）
            query: 用户查询文本
            
        Returns:
            知识库上下文字典，无结果时返回 None
        """
        knowledge_base_ids = getattr(agent, 'knowledge_base_ids', None) or []
        if not knowledge_base_ids or not self._db:
            logger.info(f'RAG 跳过: knowledge_base_ids={knowledge_base_ids}, db={bool(self._db)}')
            return None

        knowledge_config = getattr(agent, 'knowledge_config', None) or {}
        logger.info(f'RAG 开始: kb_ids={knowledge_base_ids}, config={knowledge_config}, query={query[:100]}')
        top_k = knowledge_config.get('top_k', 5)
        score_threshold = knowledge_config.get('score_threshold', 0.5)
        retrieval_mode = knowledge_config.get('retrieval_mode', None)
        rerank_enabled = knowledge_config.get('rerank_enabled', None)
        rerank_model_id = knowledge_config.get('rerank_model_id', None)

        try:
            from ai_platform.knowledge.services.retrieval_service import RetrievalService

            start_time = time.time()
            service = RetrievalService(self._db)
            results = await service.retrieve(
                query=query,
                knowledge_base_ids=knowledge_base_ids,
                top_k=top_k,
                score_threshold=score_threshold,
                retrieval_mode=retrieval_mode,
                rerank_enabled=rerank_enabled,
                rerank_model_id=rerank_model_id,
            )

            elapsed = int((time.time() - start_time) * 1000)

            logger.info(f'RAG 检索结果: {len(results)} 条')
            for r in results:
                logger.info(f'  - segment_id={r.segment_id}, score={r.score}, doc={getattr(r, "document_name", "")}, type={getattr(r, "metadata", {}).get("type", "segment")}')

            # 记录检索日志（与召回测试共用同一张日志表）
            try:
                from ai_platform.knowledge.models import KnowledgeRetrievalLog
                log = KnowledgeRetrievalLog(
                    query=query,
                    knowledge_base_ids=knowledge_base_ids,
                    retrieval_mode=retrieval_mode or 'hybrid',
                    top_k=top_k,
                    score_threshold=score_threshold,
                    result_count=len(results),
                    results=[
                        {'segment_id': r.segment_id, 'score': r.score, 'kb_id': r.knowledge_base_id}
                        for r in results
                    ],
                    rerank_applied='true' if rerank_enabled else 'false',
                    elapsed_time=elapsed,
                    source='agent',
                )
                self._db.add(log)
                await self._db.flush()
            except Exception as e:
                logger.warning(f'记录 Agent 检索日志失败: {e}')

            if not results:
                return None

            # 构建上下文文本
            context_parts = []
            for i, r in enumerate(results, 1):
                score = getattr(r, 'score', 0)
                content = getattr(r, 'content', '')
                metadata = getattr(r, 'metadata', {}) or {}

                if metadata.get('type') == 'annotation':
                    # 标注类型：显示为 Q&A 对，让 LLM 明确知道这是预设的标准答案
                    question = metadata.get('question', '')
                    context_parts.append(
                        f"[{i}] [标准问答] (相似度: {score:.2f})\n"
                        f"问题: {question}\n"
                        f"标准答案: {content}"
                    )
                else:
                    source = getattr(r, 'document_name', '') or ''
                    context_parts.append(
                        f"[{i}] (来源: {source}, 相似度: {score:.2f})\n{content}"
                    )

            context_text = '\n\n'.join(context_parts)
            summary = f"检索到 {len(results)} 条相关结果"

            return {
                'context': context_text,
                'result_count': len(results),
                'summary': summary,
                'results': [
                    {
                        'segment_id': getattr(r, 'segment_id', ''),
                        'document_name': getattr(r, 'document_name', ''),
                        'score': getattr(r, 'score', 0),
                    }
                    for r in results
                ],
            }

        except Exception as e:
            logger.warning(f'知识库检索失败: {e}')
            return None

    @staticmethod
    def _inject_knowledge_context(
        system_prompt: str,
        knowledge_context: Dict[str, Any],
    ) -> str:
        """
        将知识库检索结果注入系统提示词
        
        参考 Dify 的 RAG 注入方式：在 system prompt 末尾追加参考资料段落，
        并指示 LLM 基于资料回答，资料中无相关信息时如实告知。
        """
        context_text = knowledge_context.get('context', '')
        if not context_text:
            return system_prompt

        rag_instruction = (
            "\n\n"
            "# 参考资料\n"
            "以下是从知识库中检索到的与用户问题相关的参考资料。\n"
            "- 标记为[标准问答]的条目是预设的权威问答对，当用户问题与其匹配时，请直接使用标准答案回答，不要自行发挥。\n"
            "- 其他条目为文档参考内容，请基于这些资料回答用户的问题。\n"
            "- 如果参考资料中没有相关信息，请基于你自身的知识回答，并说明该回答未基于知识库。\n\n"
            f"{context_text}"
        )

        return system_prompt + rag_instruction
