1"""

2 LLM Provider 工厂 — 按名称/配置创建 Provider 实例。

3 v1.3.36: DeepSeek + Anthropic 硬注册（纯 httpx 实现，零 SDK 依赖）。

4

5 用法:

6 from agentos.llm.factory import create_provider

7

8 provider = create_provider("openai", model="gpt-4o", api_key="sk-...")

9 result = provider.chat([Message(...), Message(...)])

10"""

11

12 from __future__ import annotations

13

14 import os

15 from typing import Any

16

17 from agentos.llm.base import LLMProvider

18

19__all__ = ["create_provider"]

20

21_PROVIDER_REGISTRY: dict[str, tuple[str, str]] = {

22 "openai": ("agentos.llm.openai_provider", "OpenAIProvider"),

23 "deepseek": ("agentos.llm.deepseek_provider", "DeepSeekProvider"),

24 "anthropic": ("agentos.llm.anthropic_provider", "AnthropicProvider"),

25 "ollama": ("agentos.llm.ollama_provider", "OllamaProvider"),

26 "pangu": ("agentos.llm.pangu_provider", "PanguProvider"),

27}

28

29

30 def create_provider(

31 name: str = "openai",

32 *,

33 model: str = "",

34 api_key: str = "",

35 base_url: str = "",

36 **extra: Any,

37) -> LLMProvider:

38 """

39 创建 LLM Provider 实例。

40

41 Args:

42 name: 提供商名称 — "openai" / "deepseek" / "anthropic"。

43 model: 模型名称。openai: gpt-4o-mini, deepseek: deepseek-chat, anthropic: claude-sonnet-4-20250514。

44 api_key: API Key。不传则从环境变量读取。

45 base_url: 自定义端点。

46

47 Returns:

48 LLMProvider 实例。

49 """

50 if name not in _PROVIDER_REGISTRY:

51 raise ValueError(

52 f"Unknown provider: '{name}'. Available: {sorted(_PROVIDER_REGISTRY)}"

53 )

54

55 module_path, class_name = _PROVIDER_REGISTRY[name]

56

57 import importlib

58 mod = importlib.import_module(module_path)

59 cls = getattr(mod, class_name)

60

61 # Auto-detect API key from env

62 if not api_key:

63 env_var_map = {

64 "openai": "OPENAI_API_KEY",

65 "deepseek": "DEEPSEEK_API_KEY",

66 "anthropic": "ANTHROPIC_API_KEY",

67 "ollama": "OLLAMA_API_KEY",

68 "pangu": "PANGU_API_KEY",

69 }

70 api_key = os.getenv(env_var_map.get(name, ""), "")

71

72 # Default models

73 if not model:

74 defaults = {

75 "openai": "gpt-4o-mini",

76 "deepseek": "deepseek-chat",

77 "anthropic": "claude-sonnet-5-20250630",

78 "ollama": "qwen2.5:7b",

79 "pangu": "pangu-4",

80 }

81 model = defaults.get(name, "")

82

83 kwargs: dict[str, Any] = {}

84 if base_url:

85 kwargs["base_url"] = base_url

86 return cls(model=model, api_key=api_key, **kwargs, **extra)