baseUrl = $baseUrl;
$this->customModel = true;
}
else
{
$this->customModel = false;
}
$this->env = $env;
$this->set_environment();
}
protected function set_environment()
{
$this->apiKey = $this->env['apikey'];
$this->model = $this->env['model'] ?? 'gpt2';
if (!isset($this->apiKey)) {
throw new Exception('API key is required.');
}
}
protected function build_body($query, $extra = null)
{
$body = [
'inputs' => $query,
];
if ($extra) {
$body = array_merge($body, $extra);
}
return json_encode($body);
}
protected function build_url($model = null)
{
$url = $this->baseUrl;
if($this->customModel === false)
{
if ($model)
{
$url .= $model;
}
else
{
$url .= $this->model;
}
}
return $url;
}
protected function build_headers()
{
return [
'Content-Type: application/json',
'Authorization: Bearer ' . $this->apiKey,
];
}
public function generate_text($query, $extra = null)
{
$url = $this->build_url();
$body = $this->build_body($query, $extra);
$headers = $this->build_headers();
$response = $this->send_request($url, $body, $headers, 'POST');
if (isset($response['error'])) {
throw new Exception(esc_html($response['error']));
}
return $response;
}
public function list_models($params = [])
{
$models = [];
$url = $this->build_list_models_url($params);
$headers = $this->build_headers();
$max_pages = 5;
$cpage = 0;
do
{
$response = $this->send_request_list($url, null, $headers, 'GET');
if (isset($response['error'])) {
throw new Exception(esc_html($response['error']));
}
if(is_array($response))
{
foreach($response as $rmodel)
{
$models[] = $rmodel['id'];
}
}
if(!isset($response['headers']['link']))
{
break;
}
$linkHeader = $this->parse_link_header($response['headers']['link']);
$url = $linkHeader['next'] ?? null;
$cpage++;
}
while ($url && $max_pages > $cpage);
return $models;
}
protected function build_list_models_url($params)
{
$baseListUrl = 'https://huggingface.co/api/models';
$query = http_build_query($params);
return $baseListUrl . '?' . $query;
}
protected function parse_link_header($linkHeader)
{
$links = [];
if ($linkHeader) {
$parts = explode(',', $linkHeader);
foreach ($parts as $part) {
$section = explode(';', $part);
if (count($section) == 2) {
$url = trim($section[0], '<> ');
$name = trim(explode('=', $section[1])[1], '" ');
$links[$name] = $url;
}
}
}
return $links;
}
protected function send_request_list($url, $body, $headers, $method = 'POST')
{
$wp_headers = [];
foreach ($headers as $h) {
if (strpos($h, ':') !== false) {
[$k, $v] = explode(':', $h, 2);
$wp_headers[trim($k)] = trim($v);
}
}
$args = [
'method' => $method,
'headers' => $wp_headers,
'timeout' => 300,
'sslverify' => false,
];
if ($method === 'POST') {
$args['body'] = $body;
}
$response = wp_remote_request($url, $args);
if (is_wp_error($response)) {
throw new Exception(esc_html($response->get_error_message()));
}
$code = wp_remote_retrieve_response_code($response);
if ($code >= 400) {
$raw = wp_remote_retrieve_body($response);
throw new Exception('HTTP Error: ' . esc_html(sanitize_text_field($code)) . ' - ' . esc_html(sanitize_text_field($raw)));
}
$raw_headers = wp_remote_retrieve_headers($response);
$raw_body = wp_remote_retrieve_body($response);
$js = json_decode($raw_body, true);
if (is_array($js)) {
$js['headers'] = $raw_headers;
}
return $js;
}
protected function send_request($url, $body, $headers, $method = 'POST')
{
//curl require for STREAMING - using CURLOPT_WRITEFUNCTION
$ch = curl_init($url);// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_init
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt
if ($method === 'POST')
{
curl_setopt($ch, CURLOPT_POST, true);// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt
if ($this->env['stream'] == true)
{
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $data)// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt
{
//not escaped because of streaming
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
// added wp_strip_all_tags now!
echo esc_html(wp_strip_all_tags( $data ));
echo "
";
echo PHP_EOL;
ob_flush();
flush();
return strlen($data);
});
}
//must be kept because of streaming
$response = curl_exec($ch);// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_exec
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_getinfo
if ($httpCode >= 400)
{
$error = 'HTTP Error: ' . $httpCode . ' - ' . $response;
curl_close($ch);// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_close
throw new Exception(esc_html($error));
}
curl_close($ch);// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_close
$js = json_decode($response, true);
return $js;
}
protected function parse_headers($headerString)
{
$headers = [];
$lines = explode("\r\n", $headerString);
foreach ($lines as $line) {
$parts = explode(': ', $line);
if (count($parts) == 2) {
$headers[strtolower($parts[0])] = $parts[1];
}
}
return $headers;
}
}
?>