29 public $lastRequest =
"";
32 public $lastResponse =
"";
58 public function __construct(
string $type,
string $key,
string $baseUrl,
string $model,
int $timeout)
60 $this->
type = strtolower($type);
62 $this->baseUrl = rtrim($baseUrl,
'/');
63 $this->model = $model;
64 $this->timeout = $timeout;
75 public function generate(
string $system,
string $userMsg,
string $mode =
'text'): ?
string
77 switch ($this->
type) {
81 return $this->
callGoogle($system, $userMsg, $mode);
83 return $this->
callOpenAI($system, $userMsg, $mode);
97 $url = $this->baseUrl;
98 if (strpos($url,
'/chat/completions') ===
false && strpos($url,
'/generate') ===
false) {
99 $url .=
'/chat/completions';
103 "model" => $this->model,
105 array(
"role" =>
"system",
"content" => $sys),
106 array(
"role" =>
"user",
"content" => $msg)
113 if ($mode ===
'json') {
115 if (strpos($url,
'openai') !==
false || strpos($url,
'deepseek') !==
false || strpos($url,
'perplexity') !==
false || strpos($url,
'mistral') !==
false || strpos($url,
'zai') !==
false) {
116 $data[
"response_format"] = array(
"type" =>
"json_object");
120 $this->lastRequest = json_encode($data, JSON_PRETTY_PRINT);
122 return $this->
curl($url, $data, array(
"Content-Type: application/json",
"Authorization: Bearer " . $this->key));
134 private function callAnthropic(
string $sys,
string $msg,
string $mode =
'text')
137 $url = $this->baseUrl . (strpos($this->baseUrl,
'/messages') ===
false ?
'/messages' :
'');
140 "model" => $this->model,
142 "messages" => array(array(
"role" =>
"user",
"content" => $msg)),
146 $this->lastRequest = json_encode($data, JSON_PRETTY_PRINT);
148 return $this->
curl($url, $data, array(
"content-type: application/json",
"x-api-key: " . $this->key,
"anthropic-version: 2023-06-01"),
true);
160 private function callGoogle(
string $sys,
string $msg,
string $mode =
'text')
162 $url = $this->baseUrl;
165 if (strpos($url,
':generateContent') ===
false) {
166 if (strpos($url,
'/models/') ===
false) {
167 $url .=
"/models/" . $this->model;
169 $url .=
":generateContent";
172 $url .=
"?key=" . $this->key;
176 array(
"parts" => array(array(
"text" => $sys .
"\nUser: " . $msg)))
178 "generationConfig" => array(
"temperature" => 0.1)
181 $this->lastRequest = json_encode($data, JSON_PRETTY_PRINT);
183 return $this->
curl($url, $data, array(
"Content-Type: application/json"),
false,
true);
196 private function curl(
string $url, array $data, array $headers,
bool $isClaude =
false,
bool $isGemini =
false): ?
string
198 include_once DOL_DOCUMENT_ROOT.
'/core/lib/geturl.lib.php';
202 global $dolibarr_ai_allow_local_endpoints;
203 $localurl = $dolibarr_ai_allow_local_endpoints ?? 0;
208 $result =
getURLContent($url,
'POST', json_encode($data), 1, $headers, array(
'http',
'https'), $localurl, -1, 0, $this->timeout);
210 $body = (
string) ($result[
'content'] ??
'');
211 $httpCode = (int) ($result[
'http_code'] ?? 0);
212 $effectiveUrl = (
string) ($result[
'url'] ?? $url);
216 $this->lastResponse =
"HTTP " . $httpCode .
" from " . $effectiveUrl .
"\n--- body (" . strlen($body) .
" bytes) ---\n" . $body;
218 if (!empty($result[
'curl_error_no'])) {
219 return "Error: cURL #" . $result[
'curl_error_no'] .
" " . $result[
'curl_error_msg'] .
" (url=" . $effectiveUrl .
")";
222 $json = json_decode($body,
true);
224 if ($json ===
null && json_last_error() !== JSON_ERROR_NONE) {
228 $snippet = substr($body, 0, 500);
229 return "Error: Invalid JSON response from API (HTTP " . $httpCode .
", " . strlen($body) .
" bytes). Body snippet: " . ($snippet !==
'' ? $snippet :
'<empty>');
232 if (isset($json[
'error'])) {
233 $msg = $json[
'error'][
'message'] ?? json_encode($json[
'error']);
234 return "Error: API " . $msg;
239 return $json[
'content'][0][
'text'] ??
null;
242 return $json[
'candidates'][0][
'content'][
'parts'][0][
'text'] ??
null;
246 return $json[
'choices'][0][
'message'][
'content'] ??
null;
curl(string $url, array $data, array $headers, bool $isClaude=false, bool $isGemini=false)
Execute HTTP Request via cURL.
callAnthropic(string $sys, string $msg, string $mode='text')
Call Anthropic API (Claude)
callGoogle(string $sys, string $msg, string $mode='text')
Call Google Gemini API.
__construct(string $type, string $key, string $baseUrl, string $model, int $timeout)
Constructor.
generate(string $system, string $userMsg, string $mode='text')
Generate a response using the configured LLM provider.
callOpenAI(string $sys, string $msg, string $mode='text')
Call OpenAI-compatible API.
getURLContent($url, $postorget='GET', $param='', $followlocation=1, $addheaders=array(), $allowedschemes=array('http', 'https'), $localurl=0, $ssl_verifypeer=-1, $timeoutconnect=0, $timeoutresponse=0, $otherCurlOptions=array(), $morelogsuffix='')
Function to get a content from an URL (use proxy if proxy defined).
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...