PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.8.0
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.8.0
4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.5.2 All 199 releases
betterdocs / includes / AI / ModelRegistry.php

ModelRegistry.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 4.8.0, at includes/AI/ModelRegistry.php

176 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPDeveloper\BetterDocs\AI;
4
5 /**
6 * Curated, static catalogue of platforms and their chat models.
7 *
8 * Single source of truth for:
9 * - the platform selector + model dropdown in Settings (localized to React),
10 * - server-side validation that a (platform, model) pair is allowed,
11 * - the per-platform default model used when none is stored.
12 *
13 * Model identifiers move fast; update the lists here on new releases, or filter
14 * `betterdocs_ai_models` to add/replace entries without touching core.
15 *
16 * @since 4.4.0
17 */
18 class ModelRegistry {
19
20 /**
21 * Ordered list of supported platforms (id => label).
22 *
23 * @return array<string,string>
24 */
25 public static function platforms() {
26 return apply_filters( 'betterdocs_ai_platforms', array(
27 'openai' => 'OpenAI',
28 'gemini' => 'Google Gemini',
29 'claude' => 'Anthropic Claude',
30 'deepseek' => 'DeepSeek',
31 'openrouter' => 'OpenRouter',
32 ) );
33 }
34
35 /**
36 * Full model catalogue: platform => array( model_id => label ).
37 *
38 * NOTE: verify model ids against each provider's current docs at release
39 * time. Anthropic/Gemini/OpenRouter ids in particular rotate frequently.
40 *
41 * @return array<string,array<string,string>>
42 */
43 public static function catalogue() {
44 $catalogue = array(
45 'openai' => array(
46 'gpt-4o-mini' => 'GPT-4o Mini',
47 'gpt-4o' => 'GPT-4o',
48 'gpt-4.1-nano' => 'GPT-4.1 Nano',
49 'gpt-4.1-mini' => 'GPT-4.1 Mini',
50 'gpt-4.1' => 'GPT-4.1',
51 'gpt-5-nano' => 'GPT-5 Nano',
52 'gpt-5-mini' => 'GPT-5 Mini',
53 'gpt-5' => 'GPT-5',
54 'gpt-5.5' => 'GPT-5.5',
55 ),
56 // Cheapest first. Every id here is verified callable with a newly issued
57 // Google API key. `gemini-2.5-flash` / `-flash-lite` were removed: Google
58 // closed them to new users, and they still appear in ListModels while
59 // :generateContent answers 404 "no longer available to new users" — so the
60 // failure only surfaces at the first real request. The `-latest` aliases
61 // lead because Google re-points them and they cannot go stale that way.
62 'gemini' => array(
63 'gemini-flash-lite-latest' => 'Gemini Flash Lite (latest)',
64 'gemini-flash-latest' => 'Gemini Flash (latest)',
65 'gemini-3.5-flash' => 'Gemini 3.5 Flash',
66 'gemini-3.6-flash' => 'Gemini 3.6 Flash',
67 'gemini-2.5-pro' => 'Gemini 2.5 Pro',
68 'gemini-pro-latest' => 'Gemini Pro (latest)',
69 ),
70 // Cheapest/fastest first. `claude-opus-4-1` was removed because Anthropic
71 // retires it on 2026-08-05 — offering it now would hand a new install a
72 // model that starts 404ing within days of release.
73 //
74 // Opus 4.8, Opus 5 and Sonnet 5 reject `temperature` outright (400), and
75 // Opus 5 / Sonnet 5 think by default with `max_tokens` covering thinking
76 // AND the answer. ClaudeProvider handles both — see rejects_sampling()
77 // and thinks_by_default() there before adding a model here.
78 'claude' => array(
79 'claude-haiku-4-5' => 'Claude Haiku 4.5',
80 'claude-sonnet-4-5' => 'Claude Sonnet 4.5',
81 'claude-sonnet-5' => 'Claude Sonnet 5',
82 'claude-opus-4-8' => 'Claude Opus 4.8',
83 'claude-opus-5' => 'Claude Opus 5',
84 ),
85 'deepseek' => array(
86 'deepseek-chat' => 'DeepSeek Chat',
87 'deepseek-reasoner' => 'DeepSeek Reasoner',
88 ),
89 'openrouter' => array(
90 'openai/gpt-4o-mini' => 'OpenAI: GPT-4o Mini',
91 'openai/gpt-4o' => 'OpenAI: GPT-4o',
92 'anthropic/claude-sonnet-4.5' => 'Anthropic: Claude Sonnet 4.5',
93 'google/gemini-2.5-flash' => 'Google: Gemini 2.5 Flash',
94 'deepseek/deepseek-chat' => 'DeepSeek: Chat',
95 'meta-llama/llama-3.3-70b-instruct' => 'Meta: Llama 3.3 70B',
96 ),
97 );
98
99 return apply_filters( 'betterdocs_ai_models', $catalogue );
100 }
101
102 /**
103 * Default model id per platform.
104 *
105 * @return array<string,string>
106 */
107 public static function defaults() {
108 return apply_filters( 'betterdocs_ai_default_models', array(
109 'openai' => 'gpt-4o-mini',
110 // Auto-rolling alias, not a pinned version: the previous default here was
111 // gemini-2.5-flash, which Google has closed to new API keys, so every new
112 // Gemini install started on a model that 404s.
113 'gemini' => 'gemini-flash-latest',
114 // Sonnet 5 is the best speed/intelligence balance in the Claude line and
115 // is safe as a default now that ClaudeProvider drops `temperature` and
116 // raises the token floor for thinking models.
117 'claude' => 'claude-sonnet-5',
118 'deepseek' => 'deepseek-chat',
119 'openrouter' => 'openai/gpt-4o-mini',
120 ) );
121 }
122
123 /**
124 * Models for one platform (model_id => label). Empty array if unknown.
125 *
126 * @param string $platform
127 * @return array<string,string>
128 */
129 public static function models( $platform ) {
130 $catalogue = self::catalogue();
131 return isset( $catalogue[ $platform ] ) ? $catalogue[ $platform ] : array();
132 }
133
134 /**
135 * Default model id for a platform, falling back to its first listed model.
136 *
137 * @param string $platform
138 * @return string
139 */
140 public static function default_model( $platform ) {
141 $defaults = self::defaults();
142 if ( ! empty( $defaults[ $platform ] ) ) {
143 return $defaults[ $platform ];
144 }
145 $models = self::models( $platform );
146 if ( empty( $models ) ) {
147 return '';
148 }
149 reset( $models );
150 return (string) key( $models );
151 }
152
153 /**
154 * Whether a platform id is supported.
155 *
156 * @param string $platform
157 * @return bool
158 */
159 public static function has_platform( $platform ) {
160 $platforms = self::platforms();
161 return isset( $platforms[ $platform ] );
162 }
163
164 /**
165 * Whether a (platform, model) pair exists in the catalogue.
166 *
167 * @param string $platform
168 * @param string $model
169 * @return bool
170 */
171 public static function has_model( $platform, $model ) {
172 $models = self::models( $platform );
173 return isset( $models[ $model ] );
174 }
175 }
176