""" Kimi LLM实现 使用Moonshot AI的Kimi API进行文本生成 """ import os import sys from typing import Optional, Dict, Any from openai import OpenAI # 假设 .base 模块和 BaseLLM 类已存在 from .base import BaseLLM # 添加utils目录到Python路径并导入重试模块 try: current_dir = os.path.dirname(os.path.abspath(__file__)) root_dir = os.path.dirname(os.path.dirname(current_dir)) utils_dir = os.path.join(root_dir, 'utils') if utils_dir not in sys.path: sys.path.append(utils_dir) from retry_helper import with_retry, with_graceful_retry, LLM_RETRY_CONFIG except ImportError: # 如果无法导入重试模块,使用空装饰器避免报错 def with_retry(config): def decorator(func): return func return decorator LLM_RETRY_CONFIG = None class KimiLLM(BaseLLM): """Kimi LLM实现类""" def __init__(self, api_key: Optional[str] = None, model_name: Optional[str] = None): """ 初始化Kimi客户端 Args: api_key: Kimi API密钥,如果不提供则从环境变量读取 model_name: 模型名称,默认使用kimi-k2-0711-preview """ if api_key is None: api_key = os.getenv("KIMI_API_KEY") if not api_key: raise ValueError("Kimi API Key未找到!请设置KIMI_API_KEY环境变量或在初始化时提供") super().__init__(api_key, model_name) # 初始化OpenAI客户端,使用Kimi的endpoint self.client = OpenAI( api_key=self.api_key, base_url="https://api.moonshot.cn/v1" ) self.default_model = model_name or self.get_default_model() def get_default_model(self) -> str: """获取默认模型名称""" return "kimi-k2-0711-preview" @with_retry(LLM_RETRY_CONFIG) def invoke(self, system_prompt: str, user_prompt: str, **kwargs) -> str: """ 调用Kimi API生成回复 Args: system_prompt: 系统提示词 user_prompt: 用户输入 **kwargs: 其他参数,如temperature、max_tokens等 Returns: Kimi生成的回复文本 """ try: # 构建消息 messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt} ] # 智能计算max_tokens - 根据输入长度自动调整输出长度 input_length = len(system_prompt) + len(user_prompt) if input_length > 100000: # 超长文本 default_max_tokens = 81920 elif input_length > 50000: # 超长文本 default_max_tokens = 40960 elif input_length > 20000: # 长文本 default_max_tokens = 16384 elif input_length > 5000: # 中等文本 default_max_tokens = 8192 else: # 短文本 default_max_tokens = 4096 # 设置默认参数,针对长文本处理优化 params = { "model": self.default_model, "messages": messages, "temperature": kwargs.get("temperature", 0.6), # Kimi建议使用0.6 "max_tokens": kwargs.get("max_tokens", default_max_tokens), # 智能调整token限制 "stream": False } # 添加其他可选参数 if "top_p" in kwargs: params["top_p"] = kwargs["top_p"] if "presence_penalty" in kwargs: params["presence_penalty"] = kwargs["presence_penalty"] if "frequency_penalty" in kwargs: params["frequency_penalty"] = kwargs["frequency_penalty"] if "stop" in kwargs: params["stop"] = kwargs["stop"] # 输出调试信息(仅在使用Kimi时) print(f"[Kimi] 输入长度: {input_length}, 使用max_tokens: {params['max_tokens']}") # 调用API response = self.client.chat.completions.create(**params) # 提取回复内容 if response.choices and response.choices[0].message: content = response.choices[0].message.content return self.validate_response(content) else: return "" except Exception as e: print(f"Kimi API调用错误: {str(e)}") raise e def get_model_info(self) -> Dict[str, Any]: """ 获取当前模型信息 Returns: 模型信息字典 """ return { "provider": "Kimi", "model": self.default_model, "api_base": "https://api.moonshot.cn/v1", "max_context_length": "长文本支持(200K+ tokens)" } # ==================== 代码修改部分 ==================== def invoke_long_context(self, system_prompt: str, user_prompt: str, **kwargs) -> str: """ 专门用于长文本处理的调用方法 (作为invoke的兼容接口)。 此方法通过设置推荐的默认参数,然后调用通用的invoke方法来处理请求。 Args: system_prompt: 系统提示词 user_prompt: 用户输入 **kwargs: 其他参数 Returns: Kimi生成的回复文本 """ # 为长文本场景,设置一个慷慨的默认 max_tokens,仅当用户未指定时生效。 # 您原有的16384是一个非常合理的值。 kwargs.setdefault("max_tokens", 16384) # 直接调用核心的invoke方法,将所有参数(包括预设的默认值)传递给它。 return self.invoke(system_prompt, user_prompt, **kwargs)