PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 2.1.4
AI Engine – The Chatbot, AI Framework & MCP for WordPress v2.1.4
3.5.9 3.5.8 3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 3.5.2 3.5.1 3.5.0 3.4.9 3.4.8 3.4.7 0.2.1 1.6.91 0.2.2 1.6.92 0.2.3 1.6.93 0.2.4 1.6.94 0.2.5 1.6.95 0.2.6 1.6.96 0.2.7 1.6.97 0.2.8 1.6.98 0.2.9 1.6.99 0.3.0 1.7.0 0.3.1 1.7.1 0.3.2 1.7.2 0.3.3 1.7.3 0.3.4 1.7.4 0.3.5 1.7.5 0.3.6 1.7.6 0.4.0 1.7.7 0.4.1 1.7.8 0.4.2 1.7.9 0.4.3 1.8.0 0.4.4 1.8.1 0.4.5 1.8.2 0.4.6 1.8.3 0.4.7 1.8.4 0.4.8 1.8.5 0.4.9 1.8.6 0.5.0 1.8.7 0.5.1 1.8.8 0.5.2 1.8.9 0.5.3 1.9.0 0.5.4 1.9.1 0.5.5 1.9.2 0.5.6 1.9.3 0.5.7 1.9.4 0.5.8 1.9.5 0.5.9 1.9.6 0.6.0 1.9.7 0.6.1 1.9.8 0.6.2 1.9.81 0.6.3 1.9.82 0.6.4 1.9.83 0.6.5 1.9.84 0.6.6 1.9.85 0.6.7 1.9.86 0.6.8 1.9.87 0.6.9 1.9.88 0.7.0 1.9.89 0.7.1 1.9.90 0.7.2 1.9.91 0.7.3 1.9.92 0.7.4 1.9.93 0.7.5 1.9.94 0.7.6 1.9.95 0.7.7 1.9.96 0.7.8 1.9.97 0.7.9 1.9.98 0.8.0 1.9.99 0.8.1 2.0.0 0.8.2 2.0.1 0.8.3 2.0.2 0.8.4 2.0.3 0.8.5 2.0.4 0.8.6 2.0.5 0.8.7 2.0.6 0.8.8 2.0.7 0.8.9 2.0.8 0.9.0 2.0.9 0.9.2 2.1.0 0.9.3 2.1.1 0.9.4 2.1.2 0.9.5 2.1.3 0.9.6 2.1.4 0.9.7 2.1.5 0.9.8 2.1.6 0.9.81 2.1.7 0.9.82 2.1.8 0.9.83 2.1.9 0.9.84 2.2.0 0.9.85 2.2.1 0.9.86 2.2.2 0.9.87 2.2.3 0.9.88 2.2.4 0.9.89 2.2.5 0.9.9 2.2.51 0.9.91 2.2.52 0.9.92 2.2.53 0.9.93 2.2.54 0.9.94 2.2.56 0.9.95 2.2.57 0.9.96 2.2.6 0.9.97 2.2.60 0.9.98 2.2.61 0.9.99 2.2.62 1.0.0 2.2.63 1.0.01 2.2.70 1.0.1 2.2.80 1.0.2 2.2.81 1.0.3 2.2.90 1.0.4 2.2.91 1.0.5 2.2.92 1.0.6 2.2.93 1.0.7 2.2.94 1.0.8 2.2.95 1.0.9 2.3.0 1.1.0 2.3.1 1.1.1 2.3.2 1.1.2 2.3.3 1.1.3 2.3.4 1.1.4 2.3.5 1.1.5 2.3.6 1.1.6 2.3.7 1.1.7 2.3.8 1.1.8 2.3.9 1.1.9 2.4.0 1.2.0 2.4.1 1.2.1 2.4.2 1.2.2 2.4.3 1.2.21 2.4.4 1.2.3 2.4.5 1.2.30 2.4.6 1.3.0 2.4.7 1.3.1 2.4.8 1.3.2 2.4.9 1.3.3 2.5.0 1.3.31 2.5.1 1.3.32 2.5.2 1.3.33 2.5.3 1.3.34 2.5.4 1.3.35 2.5.5 1.3.36 2.5.6 1.3.37 2.5.7 1.3.38 2.5.8 1.3.39 2.5.9 1.3.40 2.6.0 1.3.41 2.6.1 1.3.42 2.6.2 1.3.43 2.6.3 1.3.44 2.6.5 1.3.45 2.6.6 1.3.46 2.6.7 1.3.47 2.6.8 1.3.48 2.6.9 1.3.49 2.7.0 1.3.50 2.7.1 1.3.51 2.7.2 1.3.52 2.7.3 1.3.53 2.7.4 1.3.54 2.7.5 1.3.56 2.7.6 1.3.57 2.7.7 1.3.58 2.7.8 1.3.59 2.7.9 1.3.60 2.8.0 1.3.61 2.8.1 1.3.62 2.8.2 1.3.63 2.8.3 1.3.64 2.8.4 1.3.65 2.8.5 1.3.66 2.8.6 1.3.67 2.8.7 1.3.68 2.8.8 1.3.69 2.8.9 1.3.70 2.9.0 1.3.71 2.9.1 1.3.72 2.9.2 1.3.73 2.9.3 1.3.74 2.9.4 1.3.75 2.9.5 1.3.76 2.9.6 1.3.77 2.9.7 1.3.78 2.9.8 1.3.79 2.9.9 1.3.80 3.0.0 1.3.81 3.0.1 1.3.82 3.0.2 1.3.83 3.0.3 1.3.84 3.0.4 1.3.85 3.0.5 1.3.86 3.0.6 1.3.87 3.0.7 1.3.88 3.0.8 1.3.89 3.0.9 1.3.90 3.1.0 1.3.91 3.1.1 1.3.92 3.1.2 1.3.93 3.1.3 1.3.94 3.1.4 1.3.95 3.1.5 1.3.96 3.1.6 1.3.97 3.1.7 1.3.98 3.1.8 1.3.99 3.1.9 1.4.0 3.2.0 1.4.1 3.2.1 1.4.2 3.2.2 1.4.3 3.2.3 1.4.4 3.2.4 1.4.5 3.2.5 1.4.6 3.2.6 1.4.7 3.2.7 1.4.8 3.2.8 1.4.9 3.2.9 1.5.0 3.3.0 1.5.1 3.3.1 1.5.2 3.3.2 1.5.3 3.3.3 1.5.4 3.3.4 1.5.5 3.3.5 1.5.6 3.3.6 1.5.7 3.3.7 1.5.8 3.3.8 1.5.9 3.3.9 1.6.0 3.4.0 1.6.1 3.4.1 1.6.2 3.4.2 1.6.3 3.4.3 1.6.5 3.4.4 1.6.51 3.4.5 1.6.52 3.4.6 1.6.53 1.6.54 1.6.55 1.6.56 1.6.57 1.6.58 1.6.59 1.6.60 1.6.61 1.6.62 1.6.63 1.6.64 1.6.65 1.6.66 1.6.67 1.6.68 trunk 1.6.69 0.0.1 1.6.70 0.0.2 1.6.71 0.0.3 1.6.72 0.0.4 1.6.73 0.0.5 1.6.74 0.0.6 1.6.75 0.0.7 1.6.76 0.0.8 1.6.77 0.0.9 1.6.78 0.1.0 1.6.79 0.1.1 1.6.81 0.1.2 1.6.82 0.1.3 1.6.83 0.1.4 1.6.84 0.1.5 1.6.85 0.1.6 1.6.86 0.1.7 1.6.87 0.1.8 1.6.88 0.1.9 1.6.89 0.2.0 1.6.90
ai-engine / classes / engines / openrouter.php
ai-engine / classes / engines Last commit date
core.php 2 years ago factory.php 2 years ago openai.php 2 years ago openrouter.php 2 years ago
openrouter.php
165 lines
1 <?php
2
3 class Meow_MWAI_Engines_OpenRouter extends Meow_MWAI_Engines_OpenAI
4 {
5
6 public function __construct( $core, $env )
7 {
8 parent::__construct( $core, $env );
9 }
10
11 protected function set_environment() {
12 $env = $this->env;
13 $this->apiKey = $env['apikey'];
14 if ( $this->envType === 'openrouter' ) {
15 $this->endpoint = apply_filters( 'mwai_openrouter_endpoint', 'https://openrouter.ai/api/v1', $this->env );
16 }
17 else {
18 throw new Exception( 'Unknown environment type: ' . $this->envType );
19 }
20 }
21
22 protected function build_headers( $query ) {
23 parent::build_headers( $query );
24 $site_url = apply_filters( 'mwai_openrouter_site_url', get_site_url(), $query );
25 $site_name = apply_filters( 'mwai_openrouter_site_name', get_bloginfo( 'name' ), $query );
26 $headers = array(
27 'Content-Type' => 'application/json',
28 'Authorization' => 'Bearer ' . $this->apiKey,
29 'HTTP-Referer' => $site_url,
30 'X-Title' => $site_name,
31 'User-Agent' => 'AI Engine',
32 );
33 return $headers;
34 }
35
36 private function truncate_float( $number, $precision = 4 ) {
37 $factor = pow( 10, $precision );
38 return floor( $number * $factor ) / $factor;
39 }
40
41 protected function get_service_name() {
42 return "OpenRouter";
43 }
44
45 public function get_models() {
46 return $this->core->get_option( 'openrouter_models' );
47 }
48
49 public function handle_tokens_usage( $reply, $query, $returned_model, $returned_in_tokens, $returned_out_tokens ) {
50 $returned_in_tokens = !is_null( $returned_in_tokens ) ? $returned_in_tokens : $reply->get_in_tokens( $query );
51 $returned_out_tokens = !is_null( $returned_out_tokens ) ? $returned_out_tokens : $reply->get_out_tokens();
52
53 // This is how to retrieve the exact number of tokens used with OpenRouter.
54 // However, it doesn't work with streaming and it slows the request.
55
56 if ( !empty( $reply->id ) ) {
57 $url = 'https://openrouter.ai/api/v1/generation?id=' . $reply->id;
58 try {
59
60 // This is the CURL way
61 // $ch = curl_init();
62 // curl_setopt( $ch, CURLOPT_URL, $url );
63 // curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
64 // curl_setopt( $ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $this->apiKey ] );
65 // curl_setopt( $ch, CURLOPT_USERAGENT, 'AI Engine' );
66 // $res = curl_exec( $ch );
67 // curl_close( $ch );
68 // $res = json_decode( $res, true );
69
70 // This is the WordPress way
71 // It currently doesn't work with OpenRouter (for mysterious reasons)
72 // $res = wp_remote_get( $url, array(
73 // 'headers' => array(
74 // 'Authorization' => 'Bearer ' . $this->apiKey,
75 // 'User-Agent' => 'AI Engine',
76 // ),
77 // 'sslverify' => false,
78 // 'user-agent' => 'AI Engine',
79 // 'timeout' => 30,
80 // 'blocking' => false,
81 // ) );
82
83 if ( isset( $res['data'] ) ) {
84 $data = $res['data'];
85 $returned_model = $data['model'];
86 $returned_in_tokens = $data['tokens_prompt'];
87 $returned_out_tokens = $data['tokens_completion'];
88 $price = $res['usage'];
89 $usage = $this->core->record_tokens_usage( $returned_model, $returned_in_tokens, $returned_out_tokens );
90 $reply->set_usage( $usage );
91 return;
92 }
93 }
94 catch ( Exception $e ) {
95 error_log( $e->getMessage() );
96 }
97 }
98
99 $usage = $this->core->record_tokens_usage( $returned_model, $returned_in_tokens, $returned_out_tokens );
100 $reply->set_usage( $usage );
101 }
102
103 public function get_price( Meow_MWAI_Query_Base $query, Meow_MWAI_Reply $reply ) {
104 return parent::get_price( $query, $reply );
105 }
106
107 public function retrieve_models() {
108 $url = 'https://openrouter.ai/api/v1/models';
109 $response = wp_remote_get( $url );
110 if ( is_wp_error( $response ) ) {
111 throw new Exception( 'AI Engine: ' . $response->get_error_message() );
112 }
113 $body = json_decode( $response['body'], true );
114 $models = array();
115 foreach ( $body['data'] as $model ) {
116 $family = "n/a";
117 $maxCompletionTokens = 4096;
118 $maxContextualTokens = 8096;
119 $priceIn = 0;
120 $priceOut = 0;
121 $family = explode( '/', $model['id'] )[0];
122 if ( isset( $model['top_provider']['max_completion_tokens'] ) ) {
123 $maxCompletionTokens = (int)$model['top_provider']['max_completion_tokens'];
124 }
125 if ( isset( $model['context_length'] ) ) {
126 $maxContextualTokens = (int)$model['context_length'];
127 }
128 if ( isset( $model['pricing']['prompt'] ) && $model['pricing']['prompt'] > 0 ) {
129 $priceIn = floatval( $model['pricing']['prompt'] ) * 1000;
130 $priceIn = $this->truncate_float( $priceIn );
131 }
132 if ( isset( $model['pricing']['completion'] ) && $model['pricing']['completion'] > 0 ) {
133 $priceOut = floatval( $model['pricing']['completion'] ) * 1000;
134 $priceOut = $this->truncate_float( $priceOut );
135 }
136
137 $tags = [ 'core', 'chat' ];
138 // If the name contains (beta), (alpha) or (preview), add 'preview' tag and remove from name
139 if ( preg_match( '/\((beta|alpha|preview)\)/i', $model['name'], $matches ) ) {
140 $tags[] = 'preview';
141 $model['name'] = preg_replace( '/\((beta|alpha|preview)\)/i', '', $model['name'] );
142 }
143 // If the name includes 'Vision', add 'vision' tag
144 if ( preg_match( '/vision/i', $model['name'], $matches ) ) {
145 $tags[] = 'vision';
146 }
147 $models[] = array(
148 'model' => $model['id'],
149 'name' => trim( $model['name'] ),
150 'family' => $family,
151 'mode' => 'chat',
152 'price' => array(
153 'in' => $priceIn,
154 'out' => $priceOut,
155 ),
156 'type' => 'token',
157 'unit' => 1 / 1000,
158 'maxCompletionTokens' => $maxCompletionTokens,
159 'maxContextualTokens' => $maxContextualTokens,
160 'tags' => $tags
161 );
162 }
163 return $models;
164 }
165 }