1 line
50 KiB
JSON
1 line
50 KiB
JSON
{"repo": "alwaysungry/hello-agent", "files": {"code/chapter07/hello_agents/core/llm.py": {"8c56dcacbd5f3df768e94cc26612fb062f9fd261": {"t": 1785747505.6324382, "n": 10945, "h": "892eac9459d3786e", "c": "import os\n\nfrom openai import OpenAI\nfrom typing import List, Dict, Any, Literal, Optional, Iterator\n\nfrom core.exceptions import HelloAgentsException\n\nSUPPORTED_PROVIDERS = Literal[\n \"openai\",\n \"deepseek\",\n \"qwen\",\n \"modelscope\",\n \"kimi\",\n \"zhipu\",\n \"vllm\",\n \"ollama\",\n \"local\",\n \"custom\",\n \"auto\",\n]\n\nclass HelloAgentsLLM:\n \"\"\"\n hello_agents的LLM客户端封装,支持与OpenAI兼容的API交互。\n 1. 多提供商支持:实现对 OpenAI、ModelScope、智谱 AI 等多种主流 LLM 服务商的无缝切换,避免框架与特定供应商绑定。\n 2. 本地模型集成:引入 VLLM 和 Ollama 这两种高性能本地部署方案,满足对数据隐私和低延迟的需求。\n 3. 自动检测机制:通过智能检测用户环境,自动选择最合适的 LLM 方案,简化配置过程,提高用户体验。\n \"\"\"\n def __init__(\n self, \n model: Optional[str] = None,\n api_key: Optional[str] = None,\n base_url: Optional[str] = None,\n provider: Optional[SUPPORTED_PROVIDERS] = None,\n temprature: Optional[float] = 0.7,\n max_tokens: Optional[int] = None,\n timeout: Optional[int] = 60,\n **kwargs \n ):\n \"\"\"\n 初始化客户端。优先使用传入的参数,其次使用环境变量。\n Args:\n model (str): 模型ID或名称。\n api_key (str): API密钥。\n base_url (str): API基础URL。\n provider (str): LLM服务提供商。\n temprature (float): 采样温度。\n max_tokens (int): 最大生成令牌数。\n timeout (int): 请求超时时间(秒)。\n \"\"\"\n \n self.model = model or os.getenv(\"LLM_MODEL_ID\")\n self.temperature = temprature or float(os.getenv(\"LLM_TEMPERATURE\", 0.7))\n self.max_tokens = max_tokens or (int(os.getenv(\"LLM_MAX_TOKENS\")) if os.getenv(\"LLM_MAX_TOKENS\") else None)\n self.kwargs = kwargs\n self.timeout = timeout or int(os.getenv(\"LLM_TIMEOUT\", 60))\n\n requested_provider = (provider or \"\").lower() if provider else None\n self.provider = provider or self._auto_detect_provider(api_key, base_url)\n\n if requested_provider == \"custom\":\n self.provider = \"custom\"\n self.api_key = api_key or os.getenv(\"LLM_API_KEY\")\n self.base_url = base_url or os.getenv(\"LLM_API_BASE_URL\")\n else:\n self.api_key, self.base_url = self._resolve_api_credentials(api_key, base_url)\n\n if not self.model:\n self.model = self._get_default_model()\n if not all([self.api_key, self.base_url]):\n raise HelloAgentsException(\"API key and base URL must be provided either as parameters or environment variables.\")\n \n self._client = self._create_client()\n\n def _auto_detect_provider(self, api_key: Optional[str], base_url: Optional[str]) -> SUPPORTED_PROVIDERS:\n \"\"\"\n 自动检测LLM提供商。\n\n 检测逻辑:\n 1. 优先检查特定提供商的环境变量(如 DEEPSEEK_API_KEY)。\n 2. 根据API密钥的格式判断\n 3. 根据base_url判断\n 4. 默认返回通用配置\n \"\"\"\n provider_env_map = [\n (\"modelscope\", \"MODELSCOPE_API_KEY\"),\n (\"openai\", \"OPENAI_API_KEY\"),\n (\"zhipu\", \"ZHIPU_API_KEY\"),\n (\"deepseek\", \"DEEPSEEK_API_KEY\"),\n (\"qwen\", \"QWEN_API_KEY\"),\n (\"kimi\", \"KIMI_API_KEY\"),\n ]\n\n for provider_name, env_var in provider_env_map:\n if os.getenv(env_var):\n return provider_name # 明确指定服务商的环境变量优先级最高\n\n candidate_base_url = (\n base_url\n or os.getenv(\"LLM_BASE_URL\")\n or os.getenv(\"LLM_API_BASE_URL\")\n or \"\"\n ).lower()\n\n if candidate_base_url:\n url_markers = {\n \"modelscope\": [\"api-inference.modelscope.cn\", \"modelscope.cn\"],\n \"openai\": [\"api.openai.com\"],\n \"zhipu\": [\"open.bigmodel.cn\", \"bigmodel.cn\", \"zhipu\"],\n \"deepseek\": [\"api.deepseek.com\"],\n \"qwen\": [\"dashscope.aliyuncs.com\", \"dashscope.com\", \"qwen\", \"qianwen\"],\n \"kimi\": [\"moonshot.cn\", \"kimiapi.cn\", \"kimi.moonshot.cn\"],\n \"ollama\": [\":11434\", \"ollama\"],\n \"vllm\": [\":8000\", \"vllm\"],\n }\n\n for provider_name, markers in url_markers.items():\n if any(marker in candidate_base_url for marker in markers):\n return provider_name\n\n if candidate_base_url.startswith(\"http://localhost\") or candidate_base_url.startswith(\"http://127.0.0.1\"):\n return \"local\"\n\n candidate_key = api_key or os.getenv(\"LLM_API_KEY\") or \"\"\n\n if candidate_key.startswith(\"ZHIPUAI_\"):\n return \"zhipu\"\n if candidate_key.startswith(\"sk-\"):\n # sk- 前缀兼容多家厂商,默认按 OpenAI 兼容接口处理\n return \"openai\"\n\n return \"auto\"\n\n def _resolve_api_credentials(self, api_key: Optional[str], base_url: Optional[str]) -> (str, str):\n \"\"\"\n 根据提供商解析API凭据。\n \"\"\"\n provider = (self.provider or \"auto\")\n\n config = {\n \"openai\": {\n \"key_env\": [\"OPENAI_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"OPENAI_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api.openai.com/v1\",\n },\n \"deepseek\": {\n \"key_env\": [\"DEEPSEEK_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"DEEPSEEK_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api.deepseek.com\",\n },\n \"qwen\": {\n \"key_env\": [\"QWEN_API_KEY\", \"DASHSCOPE_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"QWEN_BASE_URL\", \"DASHSCOPE_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n },\n \"modelscope\": {\n \"key_env\": [\"MODELSCOPE_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"MODELSCOPE_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api-inference.modelscope.cn/v1\",\n },\n \"zhipu\": {\n \"key_env\": [\"ZHIPU_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"ZHIPU_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://open.bigmodel.cn/api/paas/v4\",\n },\n \"kimi\": {\n \"key_env\": [\"KIMI_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"KIMI_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api.moonshot.cn/v1\",\n },\n \"ollama\": {\n \"key_env\": [\"OLLAMA_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"OLLAMA_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"http://localhost:11434\",\n },\n \"vllm\": {\n \"key_env\": [\"VLLM_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"VLLM_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"http://localhost:8000\",\n },\n \"local\": {\n \"key_env\": [\"LLM_API_KEY\"],\n \"base_env\": [\"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"http://localhost:8000\",\n },\n \"auto\": {\n \"key_env\": [\"LLM_API_KEY\"],\n \"base_env\": [\"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": None,\n },\n }\n\n cfg = config.get(provider, config[\"auto\"])\n\n def _first_non_empty(values):\n for val in values:\n if val:\n return val\n return None\n\n resolved_key = _first_non_empty([api_key] + [os.getenv(env) for env in cfg[\"key_env\"]])\n resolved_base = _first_non_empty([base_url] + [os.getenv(env) for env in cfg[\"base_env\"]])\n\n if not resolved_base:\n resolved_base = cfg[\"default_base\"]\n\n return resolved_key, resolved_base\n\n def _get_default_model(self) -> str:\n \"\"\"\n 获取默认模型ID。\n \"\"\"\n provider_defaults = {\n \"openai\": \"gpt-4o-mini\",\n \"deepseek\": \"deepseek-chat\",\n \"qwen\": \"qwen-turbo\",\n \"modelscope\": \"qwen-turbo\",\n \"zhipu\": \"glm-4-flash\",\n \"kimi\": \"moonshot-v1-8k\",\n \"ollama\": \"llama3\",\n \"vllm\": \"local-model\",\n \"local\": \"local-model\",\n \"custom\": \"custom-model\",\n \"auto\": \"gpt-4o-mini\",\n }\n\n return provider_defaults.get(self.provider or \"auto\", \"gpt-4o-mini\")\n\n def _create_client(self) -> OpenAI:\n \"\"\"\n 创建OpenAI客户端实例。\n \"\"\"\n print(f\"使用提供商: {self.provider}, 模型: {self.model}\")\n print(f\"API基础URL: {self.base_url}\")\n return OpenAI(\n api_key=self.api_key,\n api_base=self.base_url,\n timeout=self.timeout,\n )\n\n def think(self, messages: List[Dict[str, Any]], temperature: Optional[float] = 0.7) -> Iterator[str]:\n \"\"\"\n 调用大语言模型进行推理,返回流式响应。\n 主要的调用方法,默认使用流式响应\n Args:\n messages (List[Dict[str, Any]]): 消息列表,符合OpenAI聊天模型的输入格式。\n temperature (float): 采样温度。\n Returns:\n Iterator[str]: 流式响应生成器,每次迭代返回一部分内容\n \"\"\"\n print (f\"正在调用模型 {self.model} 模型...\")\n try:\n response = self.client.chat.completions.create(\n model=self.model,\n messages=messages,\n max_tokens=self.max_tokens,\n temperature=temperature if temperature is not None else self.temperature,\n stream=True, # Enable streaming responses\n )\n # Collect the streamed response\n print (\"大模型响应成功:\")\n for chunk in response:\n content = chunk.choices[0].delta.get(\"content\", \"\")\n if content:\n print(content, end='', flush=True)\n yield content\n print() # For newline after completion\n except Exception as e:\n print(f\"调用大语言模型API时出错: {e}\")\n raise HelloAgentsException(f\"LLM API调用失败: {e}\")\n \n def invoke(self, messages: List[Dict[str, Any]], **kwargs) -> str:\n \"\"\"\n 非流式调用大语言模型,返回完整响应。\n \"\"\"\n try:\n response = self.client.chat.completions.create(\n model=self.model,\n messages=messages,\n max_tokens=kwargs.get(\"max_tokens\", self.max_tokens),\n temperature=kwargs.get(\"temperature\", self.temperature),\n **{k: v for k, v in self.kwargs.items() if k not in ['temperature', 'max_tokens']},\n )\n return response.choices[0].message.content\n except Exception as e:\n print(f\"调用大语言模型API时出错: {e}\")\n raise HelloAgentsException(f\"LLM API调用失败: {e}\")\n \n def stream_invoke(self, messages: List[Dict[str, Any]], **kwargs) -> Iterator[str]:\n \"\"\"\n 流式调用大语言模型,与think方法相同。\n \"\"\"\n temprature = kwargs.get(\"temperature\", self.temperature)\n return self.think(messages, temperature=temprature)"}, "55c01f6ec066d6c7cb7161108080f3afb54b2231": {"t": 1785773655.0142736, "n": 10945, "h": "892eac9459d3786e", "c": "import os\n\nfrom openai import OpenAI\nfrom typing import List, Dict, Any, Literal, Optional, Iterator\n\nfrom core.exceptions import HelloAgentsException\n\nSUPPORTED_PROVIDERS = Literal[\n \"openai\",\n \"deepseek\",\n \"qwen\",\n \"modelscope\",\n \"kimi\",\n \"zhipu\",\n \"vllm\",\n \"ollama\",\n \"local\",\n \"custom\",\n \"auto\",\n]\n\nclass HelloAgentsLLM:\n \"\"\"\n hello_agents的LLM客户端封装,支持与OpenAI兼容的API交互。\n 1. 多提供商支持:实现对 OpenAI、ModelScope、智谱 AI 等多种主流 LLM 服务商的无缝切换,避免框架与特定供应商绑定。\n 2. 本地模型集成:引入 VLLM 和 Ollama 这两种高性能本地部署方案,满足对数据隐私和低延迟的需求。\n 3. 自动检测机制:通过智能检测用户环境,自动选择最合适的 LLM 方案,简化配置过程,提高用户体验。\n \"\"\"\n def __init__(\n self, \n model: Optional[str] = None,\n api_key: Optional[str] = None,\n base_url: Optional[str] = None,\n provider: Optional[SUPPORTED_PROVIDERS] = None,\n temprature: Optional[float] = 0.7,\n max_tokens: Optional[int] = None,\n timeout: Optional[int] = 60,\n **kwargs \n ):\n \"\"\"\n 初始化客户端。优先使用传入的参数,其次使用环境变量。\n Args:\n model (str): 模型ID或名称。\n api_key (str): API密钥。\n base_url (str): API基础URL。\n provider (str): LLM服务提供商。\n temprature (float): 采样温度。\n max_tokens (int): 最大生成令牌数。\n timeout (int): 请求超时时间(秒)。\n \"\"\"\n \n self.model = model or os.getenv(\"LLM_MODEL_ID\")\n self.temperature = temprature or float(os.getenv(\"LLM_TEMPERATURE\", 0.7))\n self.max_tokens = max_tokens or (int(os.getenv(\"LLM_MAX_TOKENS\")) if os.getenv(\"LLM_MAX_TOKENS\") else None)\n self.kwargs = kwargs\n self.timeout = timeout or int(os.getenv(\"LLM_TIMEOUT\", 60))\n\n requested_provider = (provider or \"\").lower() if provider else None\n self.provider = provider or self._auto_detect_provider(api_key, base_url)\n\n if requested_provider == \"custom\":\n self.provider = \"custom\"\n self.api_key = api_key or os.getenv(\"LLM_API_KEY\")\n self.base_url = base_url or os.getenv(\"LLM_API_BASE_URL\")\n else:\n self.api_key, self.base_url = self._resolve_api_credentials(api_key, base_url)\n\n if not self.model:\n self.model = self._get_default_model()\n if not all([self.api_key, self.base_url]):\n raise HelloAgentsException(\"API key and base URL must be provided either as parameters or environment variables.\")\n \n self._client = self._create_client()\n\n def _auto_detect_provider(self, api_key: Optional[str], base_url: Optional[str]) -> SUPPORTED_PROVIDERS:\n \"\"\"\n 自动检测LLM提供商。\n\n 检测逻辑:\n 1. 优先检查特定提供商的环境变量(如 DEEPSEEK_API_KEY)。\n 2. 根据API密钥的格式判断\n 3. 根据base_url判断\n 4. 默认返回通用配置\n \"\"\"\n provider_env_map = [\n (\"modelscope\", \"MODELSCOPE_API_KEY\"),\n (\"openai\", \"OPENAI_API_KEY\"),\n (\"zhipu\", \"ZHIPU_API_KEY\"),\n (\"deepseek\", \"DEEPSEEK_API_KEY\"),\n (\"qwen\", \"QWEN_API_KEY\"),\n (\"kimi\", \"KIMI_API_KEY\"),\n ]\n\n for provider_name, env_var in provider_env_map:\n if os.getenv(env_var):\n return provider_name # 明确指定服务商的环境变量优先级最高\n\n candidate_base_url = (\n base_url\n or os.getenv(\"LLM_BASE_URL\")\n or os.getenv(\"LLM_API_BASE_URL\")\n or \"\"\n ).lower()\n\n if candidate_base_url:\n url_markers = {\n \"modelscope\": [\"api-inference.modelscope.cn\", \"modelscope.cn\"],\n \"openai\": [\"api.openai.com\"],\n \"zhipu\": [\"open.bigmodel.cn\", \"bigmodel.cn\", \"zhipu\"],\n \"deepseek\": [\"api.deepseek.com\"],\n \"qwen\": [\"dashscope.aliyuncs.com\", \"dashscope.com\", \"qwen\", \"qianwen\"],\n \"kimi\": [\"moonshot.cn\", \"kimiapi.cn\", \"kimi.moonshot.cn\"],\n \"ollama\": [\":11434\", \"ollama\"],\n \"vllm\": [\":8000\", \"vllm\"],\n }\n\n for provider_name, markers in url_markers.items():\n if any(marker in candidate_base_url for marker in markers):\n return provider_name\n\n if candidate_base_url.startswith(\"http://localhost\") or candidate_base_url.startswith(\"http://127.0.0.1\"):\n return \"local\"\n\n candidate_key = api_key or os.getenv(\"LLM_API_KEY\") or \"\"\n\n if candidate_key.startswith(\"ZHIPUAI_\"):\n return \"zhipu\"\n if candidate_key.startswith(\"sk-\"):\n # sk- 前缀兼容多家厂商,默认按 OpenAI 兼容接口处理\n return \"openai\"\n\n return \"auto\"\n\n def _resolve_api_credentials(self, api_key: Optional[str], base_url: Optional[str]) -> (str, str):\n \"\"\"\n 根据提供商解析API凭据。\n \"\"\"\n provider = (self.provider or \"auto\")\n\n config = {\n \"openai\": {\n \"key_env\": [\"OPENAI_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"OPENAI_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api.openai.com/v1\",\n },\n \"deepseek\": {\n \"key_env\": [\"DEEPSEEK_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"DEEPSEEK_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api.deepseek.com\",\n },\n \"qwen\": {\n \"key_env\": [\"QWEN_API_KEY\", \"DASHSCOPE_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"QWEN_BASE_URL\", \"DASHSCOPE_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n },\n \"modelscope\": {\n \"key_env\": [\"MODELSCOPE_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"MODELSCOPE_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api-inference.modelscope.cn/v1\",\n },\n \"zhipu\": {\n \"key_env\": [\"ZHIPU_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"ZHIPU_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://open.bigmodel.cn/api/paas/v4\",\n },\n \"kimi\": {\n \"key_env\": [\"KIMI_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"KIMI_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api.moonshot.cn/v1\",\n },\n \"ollama\": {\n \"key_env\": [\"OLLAMA_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"OLLAMA_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"http://localhost:11434\",\n },\n \"vllm\": {\n \"key_env\": [\"VLLM_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"VLLM_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"http://localhost:8000\",\n },\n \"local\": {\n \"key_env\": [\"LLM_API_KEY\"],\n \"base_env\": [\"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"http://localhost:8000\",\n },\n \"auto\": {\n \"key_env\": [\"LLM_API_KEY\"],\n \"base_env\": [\"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": None,\n },\n }\n\n cfg = config.get(provider, config[\"auto\"])\n\n def _first_non_empty(values):\n for val in values:\n if val:\n return val\n return None\n\n resolved_key = _first_non_empty([api_key] + [os.getenv(env) for env in cfg[\"key_env\"]])\n resolved_base = _first_non_empty([base_url] + [os.getenv(env) for env in cfg[\"base_env\"]])\n\n if not resolved_base:\n resolved_base = cfg[\"default_base\"]\n\n return resolved_key, resolved_base\n\n def _get_default_model(self) -> str:\n \"\"\"\n 获取默认模型ID。\n \"\"\"\n provider_defaults = {\n \"openai\": \"gpt-4o-mini\",\n \"deepseek\": \"deepseek-chat\",\n \"qwen\": \"qwen-turbo\",\n \"modelscope\": \"qwen-turbo\",\n \"zhipu\": \"glm-4-flash\",\n \"kimi\": \"moonshot-v1-8k\",\n \"ollama\": \"llama3\",\n \"vllm\": \"local-model\",\n \"local\": \"local-model\",\n \"custom\": \"custom-model\",\n \"auto\": \"gpt-4o-mini\",\n }\n\n return provider_defaults.get(self.provider or \"auto\", \"gpt-4o-mini\")\n\n def _create_client(self) -> OpenAI:\n \"\"\"\n 创建OpenAI客户端实例。\n \"\"\"\n print(f\"使用提供商: {self.provider}, 模型: {self.model}\")\n print(f\"API基础URL: {self.base_url}\")\n return OpenAI(\n api_key=self.api_key,\n api_base=self.base_url,\n timeout=self.timeout,\n )\n\n def think(self, messages: List[Dict[str, Any]], temperature: Optional[float] = 0.7) -> Iterator[str]:\n \"\"\"\n 调用大语言模型进行推理,返回流式响应。\n 主要的调用方法,默认使用流式响应\n Args:\n messages (List[Dict[str, Any]]): 消息列表,符合OpenAI聊天模型的输入格式。\n temperature (float): 采样温度。\n Returns:\n Iterator[str]: 流式响应生成器,每次迭代返回一部分内容\n \"\"\"\n print (f\"正在调用模型 {self.model} 模型...\")\n try:\n response = self.client.chat.completions.create(\n model=self.model,\n messages=messages,\n max_tokens=self.max_tokens,\n temperature=temperature if temperature is not None else self.temperature,\n stream=True, # Enable streaming responses\n )\n # Collect the streamed response\n print (\"大模型响应成功:\")\n for chunk in response:\n content = chunk.choices[0].delta.get(\"content\", \"\")\n if content:\n print(content, end='', flush=True)\n yield content\n print() # For newline after completion\n except Exception as e:\n print(f\"调用大语言模型API时出错: {e}\")\n raise HelloAgentsException(f\"LLM API调用失败: {e}\")\n \n def invoke(self, messages: List[Dict[str, Any]], **kwargs) -> str:\n \"\"\"\n 非流式调用大语言模型,返回完整响应。\n \"\"\"\n try:\n response = self.client.chat.completions.create(\n model=self.model,\n messages=messages,\n max_tokens=kwargs.get(\"max_tokens\", self.max_tokens),\n temperature=kwargs.get(\"temperature\", self.temperature),\n **{k: v for k, v in self.kwargs.items() if k not in ['temperature', 'max_tokens']},\n )\n return response.choices[0].message.content\n except Exception as e:\n print(f\"调用大语言模型API时出错: {e}\")\n raise HelloAgentsException(f\"LLM API调用失败: {e}\")\n \n def stream_invoke(self, messages: List[Dict[str, Any]], **kwargs) -> Iterator[str]:\n \"\"\"\n 流式调用大语言模型,与think方法相同。\n \"\"\"\n temprature = kwargs.get(\"temperature\", self.temperature)\n return self.think(messages, temperature=temprature)"}, "bbcad1100b4c38ffcb930597792ae7af12f43d78": {"t": 1785773656.646691, "n": 10951, "h": "0c5802b77fb10450", "c": "import os\n\nfrom openai import OpenAI\nfrom typing import List, Dict, Any, Literal, Optional, Iterator\n\nfrom core.exceptions import HelloAgentsException\n\nSUPPORTED_PROVIDERS = Literal[\n \"openai\",\n \"deepseek\",\n \"qwen\",\n \"modelscope\",\n \"kimi\",\n \"zhipu\",\n \"vllm\",\n \"ollama\",\n \"local\",\n \"custom\",\n \"auto\",\n]\n\nclass HelloAgentsLLMClient:\n \"\"\"\n hello_agents的LLM客户端封装,支持与OpenAI兼容的API交互。\n 1. 多提供商支持:实现对 OpenAI、ModelScope、智谱 AI 等多种主流 LLM 服务商的无缝切换,避免框架与特定供应商绑定。\n 2. 本地模型集成:引入 VLLM 和 Ollama 这两种高性能本地部署方案,满足对数据隐私和低延迟的需求。\n 3. 自动检测机制:通过智能检测用户环境,自动选择最合适的 LLM 方案,简化配置过程,提高用户体验。\n \"\"\"\n def __init__(\n self, \n model: Optional[str] = None,\n api_key: Optional[str] = None,\n base_url: Optional[str] = None,\n provider: Optional[SUPPORTED_PROVIDERS] = None,\n temprature: Optional[float] = 0.7,\n max_tokens: Optional[int] = None,\n timeout: Optional[int] = 60,\n **kwargs \n ):\n \"\"\"\n 初始化客户端。优先使用传入的参数,其次使用环境变量。\n Args:\n model (str): 模型ID或名称。\n api_key (str): API密钥。\n base_url (str): API基础URL。\n provider (str): LLM服务提供商。\n temprature (float): 采样温度。\n max_tokens (int): 最大生成令牌数。\n timeout (int): 请求超时时间(秒)。\n \"\"\"\n \n self.model = model or os.getenv(\"LLM_MODEL_ID\")\n self.temperature = temprature or float(os.getenv(\"LLM_TEMPERATURE\", 0.7))\n self.max_tokens = max_tokens or (int(os.getenv(\"LLM_MAX_TOKENS\")) if os.getenv(\"LLM_MAX_TOKENS\") else None)\n self.kwargs = kwargs\n self.timeout = timeout or int(os.getenv(\"LLM_TIMEOUT\", 60))\n\n requested_provider = (provider or \"\").lower() if provider else None\n self.provider = provider or self._auto_detect_provider(api_key, base_url)\n\n if requested_provider == \"custom\":\n self.provider = \"custom\"\n self.api_key = api_key or os.getenv(\"LLM_API_KEY\")\n self.base_url = base_url or os.getenv(\"LLM_API_BASE_URL\")\n else:\n self.api_key, self.base_url = self._resolve_api_credentials(api_key, base_url)\n\n if not self.model:\n self.model = self._get_default_model()\n if not all([self.api_key, self.base_url]):\n raise HelloAgentsException(\"API key and base URL must be provided either as parameters or environment variables.\")\n \n self._client = self._create_client()\n\n def _auto_detect_provider(self, api_key: Optional[str], base_url: Optional[str]) -> SUPPORTED_PROVIDERS:\n \"\"\"\n 自动检测LLM提供商。\n\n 检测逻辑:\n 1. 优先检查特定提供商的环境变量(如 DEEPSEEK_API_KEY)。\n 2. 根据API密钥的格式判断\n 3. 根据base_url判断\n 4. 默认返回通用配置\n \"\"\"\n provider_env_map = [\n (\"modelscope\", \"MODELSCOPE_API_KEY\"),\n (\"openai\", \"OPENAI_API_KEY\"),\n (\"zhipu\", \"ZHIPU_API_KEY\"),\n (\"deepseek\", \"DEEPSEEK_API_KEY\"),\n (\"qwen\", \"QWEN_API_KEY\"),\n (\"kimi\", \"KIMI_API_KEY\"),\n ]\n\n for provider_name, env_var in provider_env_map:\n if os.getenv(env_var):\n return provider_name # 明确指定服务商的环境变量优先级最高\n\n candidate_base_url = (\n base_url\n or os.getenv(\"LLM_BASE_URL\")\n or os.getenv(\"LLM_API_BASE_URL\")\n or \"\"\n ).lower()\n\n if candidate_base_url:\n url_markers = {\n \"modelscope\": [\"api-inference.modelscope.cn\", \"modelscope.cn\"],\n \"openai\": [\"api.openai.com\"],\n \"zhipu\": [\"open.bigmodel.cn\", \"bigmodel.cn\", \"zhipu\"],\n \"deepseek\": [\"api.deepseek.com\"],\n \"qwen\": [\"dashscope.aliyuncs.com\", \"dashscope.com\", \"qwen\", \"qianwen\"],\n \"kimi\": [\"moonshot.cn\", \"kimiapi.cn\", \"kimi.moonshot.cn\"],\n \"ollama\": [\":11434\", \"ollama\"],\n \"vllm\": [\":8000\", \"vllm\"],\n }\n\n for provider_name, markers in url_markers.items():\n if any(marker in candidate_base_url for marker in markers):\n return provider_name\n\n if candidate_base_url.startswith(\"http://localhost\") or candidate_base_url.startswith(\"http://127.0.0.1\"):\n return \"local\"\n\n candidate_key = api_key or os.getenv(\"LLM_API_KEY\") or \"\"\n\n if candidate_key.startswith(\"ZHIPUAI_\"):\n return \"zhipu\"\n if candidate_key.startswith(\"sk-\"):\n # sk- 前缀兼容多家厂商,默认按 OpenAI 兼容接口处理\n return \"openai\"\n\n return \"auto\"\n\n def _resolve_api_credentials(self, api_key: Optional[str], base_url: Optional[str]) -> (str, str):\n \"\"\"\n 根据提供商解析API凭据。\n \"\"\"\n provider = (self.provider or \"auto\")\n\n config = {\n \"openai\": {\n \"key_env\": [\"OPENAI_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"OPENAI_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api.openai.com/v1\",\n },\n \"deepseek\": {\n \"key_env\": [\"DEEPSEEK_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"DEEPSEEK_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api.deepseek.com\",\n },\n \"qwen\": {\n \"key_env\": [\"QWEN_API_KEY\", \"DASHSCOPE_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"QWEN_BASE_URL\", \"DASHSCOPE_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n },\n \"modelscope\": {\n \"key_env\": [\"MODELSCOPE_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"MODELSCOPE_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api-inference.modelscope.cn/v1\",\n },\n \"zhipu\": {\n \"key_env\": [\"ZHIPU_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"ZHIPU_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://open.bigmodel.cn/api/paas/v4\",\n },\n \"kimi\": {\n \"key_env\": [\"KIMI_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"KIMI_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api.moonshot.cn/v1\",\n },\n \"ollama\": {\n \"key_env\": [\"OLLAMA_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"OLLAMA_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"http://localhost:11434\",\n },\n \"vllm\": {\n \"key_env\": [\"VLLM_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"VLLM_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"http://localhost:8000\",\n },\n \"local\": {\n \"key_env\": [\"LLM_API_KEY\"],\n \"base_env\": [\"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"http://localhost:8000\",\n },\n \"auto\": {\n \"key_env\": [\"LLM_API_KEY\"],\n \"base_env\": [\"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": None,\n },\n }\n\n cfg = config.get(provider, config[\"auto\"])\n\n def _first_non_empty(values):\n for val in values:\n if val:\n return val\n return None\n\n resolved_key = _first_non_empty([api_key] + [os.getenv(env) for env in cfg[\"key_env\"]])\n resolved_base = _first_non_empty([base_url] + [os.getenv(env) for env in cfg[\"base_env\"]])\n\n if not resolved_base:\n resolved_base = cfg[\"default_base\"]\n\n return resolved_key, resolved_base\n\n def _get_default_model(self) -> str:\n \"\"\"\n 获取默认模型ID。\n \"\"\"\n provider_defaults = {\n \"openai\": \"gpt-4o-mini\",\n \"deepseek\": \"deepseek-chat\",\n \"qwen\": \"qwen-turbo\",\n \"modelscope\": \"qwen-turbo\",\n \"zhipu\": \"glm-4-flash\",\n \"kimi\": \"moonshot-v1-8k\",\n \"ollama\": \"llama3\",\n \"vllm\": \"local-model\",\n \"local\": \"local-model\",\n \"custom\": \"custom-model\",\n \"auto\": \"gpt-4o-mini\",\n }\n\n return provider_defaults.get(self.provider or \"auto\", \"gpt-4o-mini\")\n\n def _create_client(self) -> OpenAI:\n \"\"\"\n 创建OpenAI客户端实例。\n \"\"\"\n print(f\"使用提供商: {self.provider}, 模型: {self.model}\")\n print(f\"API基础URL: {self.base_url}\")\n return OpenAI(\n api_key=self.api_key,\n api_base=self.base_url,\n timeout=self.timeout,\n )\n\n def think(self, messages: List[Dict[str, Any]], temperature: Optional[float] = 0.7) -> Iterator[str]:\n \"\"\"\n 调用大语言模型进行推理,返回流式响应。\n 主要的调用方法,默认使用流式响应\n Args:\n messages (List[Dict[str, Any]]): 消息列表,符合OpenAI聊天模型的输入格式。\n temperature (float): 采样温度。\n Returns:\n Iterator[str]: 流式响应生成器,每次迭代返回一部分内容\n \"\"\"\n print (f\"正在调用模型 {self.model} 模型...\")\n try:\n response = self.client.chat.completions.create(\n model=self.model,\n messages=messages,\n max_tokens=self.max_tokens,\n temperature=temperature if temperature is not None else self.temperature,\n stream=True, # Enable streaming responses\n )\n # Collect the streamed response\n print (\"大模型响应成功:\")\n for chunk in response:\n content = chunk.choices[0].delta.get(\"content\", \"\")\n if content:\n print(content, end='', flush=True)\n yield content\n print() # For newline after completion\n except Exception as e:\n print(f\"调用大语言模型API时出错: {e}\")\n raise HelloAgentsException(f\"LLM API调用失败: {e}\")\n \n def invoke(self, messages: List[Dict[str, Any]], **kwargs) -> str:\n \"\"\"\n 非流式调用大语言模型,返回完整响应。\n \"\"\"\n try:\n response = self.client.chat.completions.create(\n model=self.model,\n messages=messages,\n max_tokens=kwargs.get(\"max_tokens\", self.max_tokens),\n temperature=kwargs.get(\"temperature\", self.temperature),\n **{k: v for k, v in self.kwargs.items() if k not in ['temperature', 'max_tokens']},\n )\n return response.choices[0].message.content\n except Exception as e:\n print(f\"调用大语言模型API时出错: {e}\")\n raise HelloAgentsException(f\"LLM API调用失败: {e}\")\n \n def stream_invoke(self, messages: List[Dict[str, Any]], **kwargs) -> Iterator[str]:\n \"\"\"\n 流式调用大语言模型,与think方法相同。\n \"\"\"\n temprature = kwargs.get(\"temperature\", self.temperature)\n return self.think(messages, temperature=temprature)"}, "c97138e913ffadd9da24777e8c1f18e98315c111": {"t": 1785773658.394794, "n": 10848, "h": "7d97052069c8fb68", "c": "import os\n\nfrom openai import OpenAI\nfrom typing import List, Dict, Any, Literal, Optional, Iterator\n\nfrom core.exceptions import HelloAgentsException\n\nSUPPORTED_PROVIDERS = Literal[\n \"openai\",\n \"deepseek\",\n \"qwen\",\n \"modelscope\",\n \"kimi\",\n \"zhipu\",\n \"vllm\",\n \"ollama\",\n \"local\",\n \"custom\",\n \"auto\",\n]\n\nclass HelloAgentsLLMClient:\n \"\"\"\n hello_agents的LLM客户端封装,支持与OpenAI兼容的API交互。\n 1. 多提供商支持:实现对 OpenAI、ModelScope、智谱 AI 等多种主流 LLM 服务商的无缝切换,避免框架与特定供应商绑定。\n 2. 本地模型集成:引入 VLLM 和 Ollama 这两种高性能本地部署方案,满足对数据隐私和低延迟的需求。\n 3. 自动检测机制:通过智能检测用户环境,自动选择最合适的 LLM 方案,简化配置过程,提高用户体验。\n \"\"\"\n def __init__(\n self, \n model: Optional[str] = None,\n api_key: Optional[str] = None,\n base_url: Optional[str] = None,\n provider: Optional[SUPPORTED_PROVIDERS] = None,\n temprature: Optional[float] = 0.7,\n max_tokens: Optional[int] = None,\n timeout: Optional[int] = 60,\n **kwargs \n ):\n \"\"\"\n 初始化客户端。优先使用传入的参数,其次使用环境变量。\n Args:\n model (str): 模型ID或名称。\n api_key (str): API密钥。\n base_url (str): API基础URL。\n provider (str): LLM服务提供商。\n temprature (float): 采样温度。\n max_tokens (int): 最大生成令牌数。\n timeout (int): 请求超时时间(秒)。\n \"\"\"\n \n self.model = model or os.getenv(\"LLM_MODEL_ID\")\n self.temperature = temprature or float(os.getenv(\"LLM_TEMPERATURE\", 0.7))\n self.max_tokens = max_tokens or (int(os.getenv(\"LLM_MAX_TOKENS\")) if os.getenv(\"LLM_MAX_TOKENS\") else None)\n self.kwargs = kwargs\n self.timeout = timeout or int(os.getenv(\"LLM_TIMEOUT\", 60))\n\n requested_provider = (provider or \"\").lower() if provider else None\n self.provider = provider or self._auto_detect_provider(api_key, base_url)\n\n if requested_provider == \"custom\":\n self.provider = \"custom\"\n self.api_key = api_key or os.getenv(\"LLM_API_KEY\")\n self.base_url = base_url or os.getenv(\"LLM_API_BASE_URL\")\n else:\n self.api_key, self.base_url = self._resolve_api_credentials(api_key, base_url)\n\n if not self.model:\n self.model = self._get_default_model()\n if not all([self.api_key, self.base_url]):\n raise HelloAgentsException(\"API key and base URL must be provided either as parameters or environment variables.\")\n \n self._client = self._create_client()\n\n def _auto_detect_provider(self, api_key: Optional[str], base_url: Optional[str]) -> SUPPORTED_PROVIDERS:\n \"\"\"\n 自动检测LLM提供商。\n\n 检测逻辑:\n 1. 优先检查特定提供商的环境变量(如 DEEPSEEK_API_KEY)。\n 2. 根据API密钥的格式判断\n 3. 根据base_url判断\n 4. 默认返回通用配置\n \"\"\"\n provider_env_map = [\n (\"modelscope\", \"MODELSCOPE_API_KEY\"),\n (\"openai\", \"OPENAI_API_KEY\"),\n (\"zhipu\", \"ZHIPU_API_KEY\"),\n (\"deepseek\", \"DEEPSEEK_API_KEY\"),\n (\"qwen\", \"QWEN_API_KEY\"),\n (\"kimi\", \"KIMI_API_KEY\"),\n ]\n\n for provider_name, env_var in provider_env_map:\n if os.getenv(env_var):\n return provider_name # 明确指定服务商的环境变量优先级最高\n\n candidate_base_url = (\n base_url\n or os.getenv(\"LLM_BASE_URL\")\n or os.getenv(\"LLM_API_BASE_URL\")\n or \"\"\n ).lower()\n\n if candidate_base_url:\n url_markers = {\n \"modelscope\": [\"api-inference.modelscope.cn\", \"modelscope.cn\"],\n \"openai\": [\"api.openai.com\"],\n \"zhipu\": [\"open.bigmodel.cn\", \"bigmodel.cn\", \"zhipu\"],\n \"deepseek\": [\"api.deepseek.com\"],\n \"qwen\": [\"dashscope.aliyuncs.com\", \"dashscope.com\", \"qwen\", \"qianwen\"],\n \"kimi\": [\"moonshot.cn\", \"kimiapi.cn\", \"kimi.moonshot.cn\"],\n \"ollama\": [\":11434\", \"ollama\"],\n \"vllm\": [\":8000\", \"vllm\"],\n }\n\n for provider_name, markers in url_markers.items():\n if any(marker in candidate_base_url for marker in markers):\n return provider_name\n\n if candidate_base_url.startswith(\"http://localhost\") or candidate_base_url.startswith(\"http://127.0.0.1\"):\n return \"local\"\n\n candidate_key = api_key or os.getenv(\"LLM_API_KEY\") or \"\"\n\n if candidate_key.startswith(\"ZHIPUAI_\"):\n return \"zhipu\"\n if candidate_key.startswith(\"sk-\"):\n # sk- 前缀兼容多家厂商,默认按 OpenAI 兼容接口处理\n return \"openai\"\n\n return \"auto\"\n\n def _resolve_api_credentials(self, api_key: Optional[str], base_url: Optional[str]) -> (str, str):\n \"\"\"\n 根据提供商解析API凭据。\n \"\"\"\n provider = (self.provider or \"auto\")\n\n config = {\n \"openai\": {\n \"key_env\": [\"OPENAI_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"OPENAI_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api.openai.com/v1\",\n },\n \"deepseek\": {\n \"key_env\": [\"DEEPSEEK_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"DEEPSEEK_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api.deepseek.com\",\n },\n \"qwen\": {\n \"key_env\": [\"QWEN_API_KEY\", \"DASHSCOPE_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"QWEN_BASE_URL\", \"DASHSCOPE_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n },\n \"modelscope\": {\n \"key_env\": [\"MODELSCOPE_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"MODELSCOPE_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api-inference.modelscope.cn/v1\",\n },\n \"zhipu\": {\n \"key_env\": [\"ZHIPU_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"ZHIPU_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://open.bigmodel.cn/api/paas/v4\",\n },\n \"kimi\": {\n \"key_env\": [\"KIMI_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"KIMI_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"https://api.moonshot.cn/v1\",\n },\n \"ollama\": {\n \"key_env\": [\"OLLAMA_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"OLLAMA_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"http://localhost:11434\",\n },\n \"vllm\": {\n \"key_env\": [\"VLLM_API_KEY\", \"LLM_API_KEY\"],\n \"base_env\": [\"VLLM_BASE_URL\", \"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"http://localhost:8000\",\n },\n \"local\": {\n \"key_env\": [\"LLM_API_KEY\"],\n \"base_env\": [\"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": \"http://localhost:8000\",\n },\n \"auto\": {\n \"key_env\": [\"LLM_API_KEY\"],\n \"base_env\": [\"LLM_BASE_URL\", \"LLM_API_BASE_URL\"],\n \"default_base\": None,\n },\n }\n\n cfg = config.get(provider, config[\"auto\"])\n\n def _first_non_empty(values):\n for val in values:\n if val:\n return val\n return None\n\n resolved_key = _first_non_empty([api_key] + [os.getenv(env) for env in cfg[\"key_env\"]])\n resolved_base = _first_non_empty([base_url] + [os.getenv(env) for env in cfg[\"base_env\"]])\n\n if not resolved_base:\n resolved_base = cfg[\"default_base\"]\n\n return resolved_key, resolved_base\n\n def _get_default_model(self) -> str:\n \"\"\"\n 获取默认模型ID。\n \"\"\"\n provider_defaults = {\n \"openai\": \"gpt-4o-mini\",\n \"deepseek\": \"deepseek-chat\",\n \"qwen\": \"qwen-turbo\",\n \"modelscope\": \"qwen-turbo\",\n \"zhipu\": \"glm-4-flash\",\n \"kimi\": \"moonshot-v1-8k\",\n \"ollama\": \"llama3\",\n \"vllm\": \"local-model\",\n \"local\": \"local-model\",\n \"custom\": \"custom-model\",\n \"auto\": \"gpt-4o-mini\",\n }\n\n return provider_defaults.get(self.provider or \"auto\", \"gpt-4o-mini\")\n\n def _create_client(self) -> OpenAI:\n \"\"\"\n 创建OpenAI客户端实例。\n \"\"\"\n return OpenAI(\n api_key=self.api_key,\n api_base=self.base_url,\n timeout=self.timeout,\n )\n\n def think(self, messages: List[Dict[str, Any]], temperature: Optional[float] = 0.7) -> Iterator[str]:\n \"\"\"\n 调用大语言模型进行推理,返回流式响应。\n 主要的调用方法,默认使用流式响应\n Args:\n messages (List[Dict[str, Any]]): 消息列表,符合OpenAI聊天模型的输入格式。\n temperature (float): 采样温度。\n Returns:\n Iterator[str]: 流式响应生成器,每次迭代返回一部分内容\n \"\"\"\n print (f\"正在调用模型 {self.model} 模型...\")\n try:\n response = self.client.chat.completions.create(\n model=self.model,\n messages=messages,\n max_tokens=self.max_tokens,\n temperature=temperature if temperature is not None else self.temperature,\n stream=True, # Enable streaming responses\n )\n # Collect the streamed response\n print (\"大模型响应成功:\")\n for chunk in response:\n content = chunk.choices[0].delta.get(\"content\", \"\")\n if content:\n print(content, end='', flush=True)\n yield content\n print() # For newline after completion\n except Exception as e:\n print(f\"调用大语言模型API时出错: {e}\")\n raise HelloAgentsException(f\"LLM API调用失败: {e}\")\n \n def invoke(self, messages: List[Dict[str, Any]], **kwargs) -> str:\n \"\"\"\n 非流式调用大语言模型,返回完整响应。\n \"\"\"\n try:\n response = self.client.chat.completions.create(\n model=self.model,\n messages=messages,\n max_tokens=kwargs.get(\"max_tokens\", self.max_tokens),\n temperature=kwargs.get(\"temperature\", self.temperature),\n **{k: v for k, v in self.kwargs.items() if k not in ['temperature', 'max_tokens']},\n )\n return response.choices[0].message.content\n except Exception as e:\n print(f\"调用大语言模型API时出错: {e}\")\n raise HelloAgentsException(f\"LLM API调用失败: {e}\")\n \n def stream_invoke(self, messages: List[Dict[str, Any]], **kwargs) -> Iterator[str]:\n \"\"\"\n 流式调用大语言模型,与think方法相同。\n \"\"\"\n temprature = kwargs.get(\"temperature\", self.temperature)\n return self.think(messages, temperature=temprature)"}}}} |