o
    pi{                     @  s6  d Z ddlmZ ddlZddlZddlmZmZ ddlm	Z	m
Z
mZmZ ddlmZ dZdZd	Zd	Zd
ZeddG dd dZeddG dd dZeddG dd dZeddG dd dZeddG dd dZeddG dd dZeddG dd dZd%ddZG dd  d Zd&d#d$ZdS )'u   纯粹的 LLM 调用模块：输入请求，输出响应。

设计原则：
1) 不保存任何会话状态，不维护上下文。
2) 不拼接 Prompt，不注入 system 提示词。
3) 不做总结或后处理，只做参数透传和结果解析。
    )annotationsN)	dataclassfield)AnyLiteralOptionalSequence)OpenAIzhttps://api.deepseek.comzdeepseek-chatg      ?i   T)slotsc                   @  s6   e Zd ZU dZed Zded< ded< dZded	< dS )
Messageu   单条对话消息。

    - role: 消息角色（如 system/user/assistant/tool）
    - content: 消息文本内容
    - name: 可选，通常用于 function calling 场景标注函数名
    )systemuser	assistanttoolRoleTyperolestrcontentNOptional[str]name)__name__
__module____qualname____doc__r   r   __annotations__r    r   r   )/home/dore/onebot/Bot_Ero/core/llm/llm.pyr      s   
 r   c                   @  sB   e Zd ZU dZeZded< eZded< e	Z
ded< eZded< d	S )
GenerationConfigu   模型生成配置。r   modelfloattemperaturetop_pint
max_tokensN)r   r   r   r   DEFAULT_MODELr   r   DEFAULT_TEMPERATUREr    DEFAULT_TOP_Pr!   DEFAULT_MAX_TOKENSr#   r   r   r   r   r   )   s   
 r   c                   @  s*   e Zd ZU dZded< ded< ded< dS )ToolSpecu   用于描述单个 function 的工具定义。

    - name: 函数名称
    - description: 函数用途描述
    - parameters: JSON Schema 风格参数定义
    r   r   descriptionzdict[str, Any]
parametersN)r   r   r   r   r   r   r   r   r   r(   7   s
   
 r(   c                   @  s,   e Zd ZU dZded< eedZded< dS )ToolCallu   用于描述模型发起的一次 function 调用。

    - name: 被调用函数名
    - arguments: 调用参数列表（按顺序展开）
    r   r   default_factoryz	list[Any]	argumentsN)r   r   r   r   r   r   listr.   r   r   r   r   r+   E   s   
 r+   c                   @  s8   e Zd ZU dZded< eedZded< dZded	< dS )
ChatRequestu   聊天请求体。

    - messages: 标准消息列表（调用方负责组织上下文）
    - config: 本次调用的生成参数
    - tools: function calling 的工具定义列表（可选）
    zSequence[Message]messagesr,   r   configNzOptional[Sequence[ToolSpec]]tools)	r   r   r   r   r   r   r   r2   r3   r   r   r   r   r0   Q   s
   
 r0   c                   @  s6   e Zd ZU dZdZded< dZded< dZded< dS )Usageu%   本次调用的 token 消耗统计。r   r"   prompt_tokenscompletion_tokenstotal_tokensN)r   r   r   r   r5   r   r6   r7   r   r   r   r   r4   _   s
   
 r4   c                   @  s<   e Zd ZU dZded< ded< ded< eedZded	< d
S )ChatResponseu   聊天响应体。

    - message: 模型返回的纯文本
    - finish_reason: 结束原因（如 stop/length/tool_calls 等）
    - usage: token 使用量
    r   messagefinish_reasonr4   usager,   zlist[ToolCall]
tool_callsN)r   r   r   r   r   r   r/   r<   r   r   r   r   r8   h   s   
 r8   returnr   c                  C  s*   t d} | du rdS t|  }|pdS )u5   从环境变量读取 API Key，并做空白清洗。DEEPSEEK_API_KEYN)osgetenvr   strip)rawkeyr   r   r   _api_key_from_envw   s
   
rD   c                   @  s"   e Zd ZddddZdddZdS )LLMNapi_keyr   base_urlc                 C  s,   |pt  }|stdt||ptd| _d S )Nz?Missing DeepSeek API key: set DEEPSEEK_API_KEY or pass api_key=)rF   rG   )rD   
ValueErrorr	   DEFAULT_API_BASEclient)selfrF   rG   rC   r   r   r   __init__   s   
zLLM.__init__requestr0   r=   r8   c              
   C  s  g }|j D ]}|j|jd}|jr|j|d< || q|jj||jj|jj|jj	dd}|j
r:dd |j
D |d< | jjjjdi |}|jd }|jjpOd	}|j}	g }
t|jd
dp]g D ]T}tt|dddd	pkd	}g }t|tr| rzt|}t|tr|}nt|tr|g}n|g}W n ty   |g}Y nw |
ttt|dddd	pd	|d q^t| |jpdtt|	ddpdt|	ddpdt|	ddpdd|
dS )u9   执行一次聊天调用：ChatRequest -> ChatResponse。r   r   r   F)r   r1   r    r!   r#   streamc                 S  s$   g | ]}d |j |j|jddqS )functionr   r)   r*   )typerP   rQ   ).0r   r   r   r   
<listcomp>   s    	zLLM.chat.<locals>.<listcomp>r3   r    r<   NrP   r.   )r   r.   unknownr5   r6   r7   )r5   r6   r7   )r9   r:   r;   r<   r   )r1   r   r   r   appendr2   r   r    r!   r#   r3   rJ   chatcompletionscreatechoicesr9   r;   getattr
isinstancer   rA   jsonloadsr/   dict	Exceptionr+   r8   r:   r4   )rK   rM   payload_messagesmsgpayloadparamsresponsechoicer   r;   r<   	tool_callargs_raw	args_listparsedr   r   r   rX      sj   

		





zLLM.chat)NN)rF   r   rG   r   )rM   r0   r=   r8   )r   r   r   rL   rX   r   r   r   r   rE      s    rE   	user_textr   c                 C  s.   ddl m}m} ||td| dgd}|jS )u   兼容旧调用入口：单条用户输入 -> 纯文本输出。

    注意：该函数不注入系统提示词，不维护历史，仅做最薄封装。
    r   )CompletionContextcompleter   rN   )r1   )core.llm.chat_facaderm   rn   r   r9   )rl   rm   rn   outcomer   r   r   chat_assistant_reply   s   rq   )r=   r   )rl   r   r=   r   )r   
__future__r   r^   r?   dataclassesr   r   typingr   r   r   r   openair	   rI   r$   r%   r&   r'   r   r   r(   r+   r0   r4   r8   rD   rE   rq   r   r   r   r   <module>   s:    
	T