PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 2.3.0
AI Engine – The Chatbot, AI Framework & MCP for WordPress v2.3.0
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
anthropic.php 2 years ago core.php 2 years ago factory.php 2 years ago google.php 2 years ago huggingface.php 2 years ago openai.php 2 years ago openrouter.php 2 years ago
openrouter.php
166 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 }
15
16 protected function build_url( $query, $endpoint = null ) {
17 $endpoint = apply_filters( 'mwai_openrouter_endpoint', 'https://openrouter.ai/api/v1', $this->env );
18 $url = parent::build_url( $query, $endpoint );
19 return $url;
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,
50 $returned_in_tokens, $returned_out_tokens, $returned_price = null ) {
51
52 // If streaming is not enabled, we probably have all the data we need
53 $everything_is_set = !is_null( $returned_model ) && !is_null( $returned_in_tokens ) && !is_null( $returned_out_tokens );
54
55 // Clean up the data
56 $returned_in_tokens = !is_null( $returned_in_tokens ) ?
57 $returned_in_tokens : $reply->get_in_tokens( $query );
58 $returned_out_tokens = !is_null( $returned_out_tokens ) ?
59 $returned_out_tokens : $reply->get_out_tokens();
60 $returned_price = !is_null( $returned_price ) ?
61 $returned_price : $reply->get_price();
62
63 // If everything is not set, we can make a request to get the usage data
64 if ( !empty( $reply->id ) && !$everything_is_set ) {
65 $url = 'https://openrouter.ai/api/v1/generation?id=' . $reply->id;
66 try {
67 $ch = curl_init();
68 curl_setopt( $ch, CURLOPT_URL, $url );
69 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
70 curl_setopt( $ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $this->apiKey ] );
71 curl_setopt( $ch, CURLOPT_USERAGENT, 'AI Engine' );
72 $res = curl_exec( $ch );
73 curl_close( $ch );
74 $res = json_decode( $res, true );
75 if ( isset( $res['data'] ) ) {
76 $data = $res['data'];
77 $returned_model = $data['model'];
78 $returned_in_tokens = $data['tokens_prompt'];
79 $returned_out_tokens = $data['tokens_completion'];
80 $returned_price = $data['total_cost'];
81 }
82 }
83 catch ( Exception $e ) {
84 error_log( $e->getMessage() );
85 }
86 }
87
88 // Record the usage
89 $usage = $this->core->record_tokens_usage(
90 $returned_model,
91 $returned_in_tokens,
92 $returned_out_tokens,
93 $returned_price
94 );
95
96 // Set the usage in the reply
97 $reply->set_usage( $usage );
98 }
99
100 public function get_price( Meow_MWAI_Query_Base $query, Meow_MWAI_Reply $reply ) {
101 $price = $reply->get_price();
102 if ( is_null( $price ) ) {
103 $price = parent::get_price( $query, $reply );
104 }
105 return $price;
106 }
107
108 public function retrieve_models() {
109 $url = 'https://openrouter.ai/api/v1/models';
110 $response = wp_remote_get( $url );
111 if ( is_wp_error( $response ) ) {
112 throw new Exception( 'AI Engine: ' . $response->get_error_message() );
113 }
114 $body = json_decode( $response['body'], true );
115 $models = array();
116 foreach ( $body['data'] as $model ) {
117 $family = "n/a";
118 $maxCompletionTokens = 4096;
119 $maxContextualTokens = 8096;
120 $priceIn = 0;
121 $priceOut = 0;
122 $family = explode( '/', $model['id'] )[0];
123 if ( isset( $model['top_provider']['max_completion_tokens'] ) ) {
124 $maxCompletionTokens = (int)$model['top_provider']['max_completion_tokens'];
125 }
126 if ( isset( $model['context_length'] ) ) {
127 $maxContextualTokens = (int)$model['context_length'];
128 }
129 if ( isset( $model['pricing']['prompt'] ) && $model['pricing']['prompt'] > 0 ) {
130 $priceIn = floatval( $model['pricing']['prompt'] ) * 1000;
131 $priceIn = $this->truncate_float( $priceIn );
132 }
133 if ( isset( $model['pricing']['completion'] ) && $model['pricing']['completion'] > 0 ) {
134 $priceOut = floatval( $model['pricing']['completion'] ) * 1000;
135 $priceOut = $this->truncate_float( $priceOut );
136 }
137
138 $tags = [ 'core', 'chat' ];
139 // If the name contains (beta), (alpha) or (preview), add 'preview' tag and remove from name
140 if ( preg_match( '/\((beta|alpha|preview)\)/i', $model['name'], $matches ) ) {
141 $tags[] = 'preview';
142 $model['name'] = preg_replace( '/\((beta|alpha|preview)\)/i', '', $model['name'] );
143 }
144 // If the name includes 'Vision', add 'vision' tag
145 if ( preg_match( '/vision/i', $model['name'], $matches ) ) {
146 $tags[] = 'vision';
147 }
148 $models[] = array(
149 'model' => $model['id'],
150 'name' => trim( $model['name'] ),
151 'family' => $family,
152 'mode' => 'chat',
153 'price' => array(
154 'in' => $priceIn,
155 'out' => $priceOut,
156 ),
157 'type' => 'token',
158 'unit' => 1 / 1000,
159 'maxCompletionTokens' => $maxCompletionTokens,
160 'maxContextualTokens' => $maxContextualTokens,
161 'tags' => $tags
162 );
163 }
164 return $models;
165 }
166 }