1ae09ced4SAndreas Gohr<?php 2ae09ced4SAndreas Gohr 3ae09ced4SAndreas Gohruse dokuwiki\plugin\aichat\AbstractCLI; 4ae09ced4SAndreas Gohruse splitbrain\phpcli\Options; 5ae09ced4SAndreas Gohr 6ae09ced4SAndreas Gohr/** 7ae09ced4SAndreas Gohr * DokuWiki Plugin aichat (CLI Component) 8ae09ced4SAndreas Gohr * 9ae09ced4SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 10ae09ced4SAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de> 11ae09ced4SAndreas Gohr */ 12ae09ced4SAndreas Gohrclass cli_plugin_aichat_dev extends AbstractCLI 13ae09ced4SAndreas Gohr{ 14ae09ced4SAndreas Gohr /** @inheritDoc */ 15ae09ced4SAndreas Gohr protected function setup(Options $options) 16ae09ced4SAndreas Gohr { 17ae09ced4SAndreas Gohr $options->setHelp('Helps with development of this plugin'); 18ae09ced4SAndreas Gohr 19ae09ced4SAndreas Gohr $options->registerCommand('update', 'Update the model data'); 20ae09ced4SAndreas Gohr } 21ae09ced4SAndreas Gohr 22ae09ced4SAndreas Gohr /** @inheritDoc */ 23ae09ced4SAndreas Gohr protected function main(Options $options) 24ae09ced4SAndreas Gohr { 25ae09ced4SAndreas Gohr parent::main($options); 26ae09ced4SAndreas Gohr 27ae09ced4SAndreas Gohr switch ($options->getCmd()) { 28ae09ced4SAndreas Gohr 29ae09ced4SAndreas Gohr case 'update': 30ae09ced4SAndreas Gohr $this->updateModelData(); 31ae09ced4SAndreas Gohr break; 32ae09ced4SAndreas Gohr default: 33ae09ced4SAndreas Gohr echo $options->help(); 34ae09ced4SAndreas Gohr } 35ae09ced4SAndreas Gohr } 36ae09ced4SAndreas Gohr 37ae09ced4SAndreas Gohr protected function updateModelData() 38ae09ced4SAndreas Gohr { 39ae09ced4SAndreas Gohr 40ae09ced4SAndreas Gohr $http = new \dokuwiki\HTTP\DokuHTTPClient(); 41ae09ced4SAndreas Gohr $url = 'https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json'; 42ae09ced4SAndreas Gohr $response = $http->get($url); 43ae09ced4SAndreas Gohr if ($response === false) { 44ae09ced4SAndreas Gohr $this->error('Failed to fetch model data'); 45ae09ced4SAndreas Gohr return 1; 46ae09ced4SAndreas Gohr } 47ae09ced4SAndreas Gohr $models = json_decode($response, true, 512, JSON_THROW_ON_ERROR); 48ae09ced4SAndreas Gohr 49ae09ced4SAndreas Gohr $ourProviders = [ 50ae09ced4SAndreas Gohr 'anthropic' => [ 51ae09ced4SAndreas Gohr 'name' => 'Anthropic', 52ae09ced4SAndreas Gohr ], 53ae09ced4SAndreas Gohr 'groq' => [ 54ae09ced4SAndreas Gohr 'name' => 'Groq', 55ae09ced4SAndreas Gohr 'skip' => '/-preview$/' 56ae09ced4SAndreas Gohr ], 57ae09ced4SAndreas Gohr 'mistral' => [ 58ae09ced4SAndreas Gohr 'name' => 'Mistral', 59ae09ced4SAndreas Gohr 'skip' => '/-\d\d\d\d$/', 60ae09ced4SAndreas Gohr ], 61ae09ced4SAndreas Gohr 'openai' => [ 62ae09ced4SAndreas Gohr 'name' => 'OpenAI', 63ae09ced4SAndreas Gohr 'skip' => '/(-\d\d\d\d-\d\d-\d\d|-preview|-\d\d\d\d)$|^ft:/' 64ae09ced4SAndreas Gohr ], 65ae09ced4SAndreas Gohr 'reka' => [ 66ae09ced4SAndreas Gohr 'name' => 'Reka', 67ae09ced4SAndreas Gohr ], 68ae09ced4SAndreas Gohr 'voyage' => [ 69ae09ced4SAndreas Gohr 'name' => 'VoyageAI', 70ae09ced4SAndreas Gohr 'skip' => '/-(01|02)(-|$)/', // outdated models 71ae09ced4SAndreas Gohr ], 72*10789c17SAndreas Gohr 'gemini' => [ 73*10789c17SAndreas Gohr 'name' => 'Gemini', 74*10789c17SAndreas Gohr 'skip' => '/(-preview|-exp|-\d\d\d$)/' 75*10789c17SAndreas Gohr ], 76ae09ced4SAndreas Gohr ]; 77ae09ced4SAndreas Gohr 78ae09ced4SAndreas Gohr // load existing models 79ae09ced4SAndreas Gohr foreach ($ourProviders as $provider => $data) { 80ae09ced4SAndreas Gohr $ourProviders[$provider]['models'] = json_decode( 81ae09ced4SAndreas Gohr file_get_contents(__DIR__ . '/../Model/' . $data['name'] . '/' . 'models.json'), 82ae09ced4SAndreas Gohr true 83ae09ced4SAndreas Gohr ); 84ae09ced4SAndreas Gohr } 85ae09ced4SAndreas Gohr 86ae09ced4SAndreas Gohr // update models 87ae09ced4SAndreas Gohr foreach ($models as $model => $data) { 88ae09ced4SAndreas Gohr if (!isset($ourProviders[$data['litellm_provider']])) continue; 89ae09ced4SAndreas Gohr if (!in_array($data['mode'], ['chat', 'embedding'])) continue; 90ae09ced4SAndreas Gohr $provider = $data['litellm_provider']; 91ae09ced4SAndreas Gohr $model = explode('/', $model); 92ae09ced4SAndreas Gohr $model = array_pop($model); 93ae09ced4SAndreas Gohr 94ae09ced4SAndreas Gohr if (isset($ourProviders[$provider]['skip']) && preg_match($ourProviders[$provider]['skip'], $model)) { 95ae09ced4SAndreas Gohr $this->info('Skipping ' . $provider . ' ' . $model); 96ae09ced4SAndreas Gohr continue; 97ae09ced4SAndreas Gohr } 98ae09ced4SAndreas Gohr $this->success("$provider $model"); 99ae09ced4SAndreas Gohr 100ae09ced4SAndreas Gohr $oldmodel = $ourProviders[$provider]['models'][$data['mode']][$model] ?? []; 101ae09ced4SAndreas Gohr $newmodel = [ 102ae09ced4SAndreas Gohr "description" => $oldmodel['description'] ?? $data['source'] ?? '', 103ae09ced4SAndreas Gohr "inputTokens" => $data['max_input_tokens'] ?? $data['max_tokens'], 104ae09ced4SAndreas Gohr "inputTokenPrice" => round($data['input_cost_per_token'] * 1_000_000, 2), 105ae09ced4SAndreas Gohr ]; 106ae09ced4SAndreas Gohr 107ae09ced4SAndreas Gohr if ($data['mode'] === 'chat') { 108ae09ced4SAndreas Gohr $newmodel['outputTokens'] = $data['max_output_tokens']; 109ae09ced4SAndreas Gohr $newmodel['outputTokenPrice'] = round($data['output_cost_per_token'] * 1_000_000, 2); 110ae09ced4SAndreas Gohr } else { 111ae09ced4SAndreas Gohr if (isset($oldmodel['dimensions'])) { 112ae09ced4SAndreas Gohr $newmodel['dimensions'] = $oldmodel['dimensions']; 113ae09ced4SAndreas Gohr } else { 114ae09ced4SAndreas Gohr $this->warning('No dimensions for ' . $provider . ' ' . $model . '. Check manually!'); 115ae09ced4SAndreas Gohr $newmodel['dimensions'] = 1536; 116ae09ced4SAndreas Gohr } 117ae09ced4SAndreas Gohr } 118ae09ced4SAndreas Gohr $ourProviders[$provider]['models'][$data['mode']][$model] = $newmodel; 119ae09ced4SAndreas Gohr } 120ae09ced4SAndreas Gohr 121ae09ced4SAndreas Gohr // save models 122ae09ced4SAndreas Gohr foreach ($ourProviders as $data) { 123ae09ced4SAndreas Gohr file_put_contents( 124ae09ced4SAndreas Gohr __DIR__ . '/../Model/' . $data['name'] . '/' . 'models.json', 125ae09ced4SAndreas Gohr json_encode($data['models'], JSON_PRETTY_PRINT) 126ae09ced4SAndreas Gohr ); 127ae09ced4SAndreas Gohr } 128ae09ced4SAndreas Gohr 129ae09ced4SAndreas Gohr return 0; 130ae09ced4SAndreas Gohr } 131ae09ced4SAndreas Gohr} 132