AI

object

%AI

/phlo/resources/AI/AI.phlo

Unified AI facade with engine auto-detect

One door for every engine: %AI->chat reads the engine from the model name, so gpt goes to OpenAI, claude to Claude and gemini to Gemini, while via names one outright. Every engine answers in the same shape, with answer, model, finish and a token count, so swapping models is a one-word change. A model no rule matches falls back to OpenAI, and each engine still needs credentials of its own.

aifacadellmstreamingtoolsembeddings
prop

%AI -> model:string

line 11
Dit item definieert een AI-model met de identificatie 'gpt-5.4-mini'.
'gpt-5.4-mini'
const

AI :: engines

line 12
Definieert een mapping van AI-engine-identifiers naar hun respectieve namen, waardoor eenvoudige verwijzing en integratie binnen Phlo-toepassingen mogelijk is.
['claude' => 'Claude', 'gpt' => 'OpenAI', 'chatgpt' => 'OpenAI', 'o1' => 'OpenAI', 'o3' => 'OpenAI', 'o4' => 'OpenAI', 'deepseek' => 'DeepSeek', 'gemini' => 'Gemini', 'grok' => 'Grok']
static

AI :: http (string $url, array $headers, bool $json = true, mixed $post = null):string

line 13
Verzendt een HTTP-verzoek naar de opgegeven URL met optionele headers, JSON-payload en POST-gegevens, met de mogelijkheid om de time-outperiode aan te passen.
HTTP($url, $headers, $json, $post, timeout: 300)
method

%AI -> resolve (...$args):array

line 14
Bepaalt de AI-engine die moet worden gebruikt op basis van de opgegeven argumenten, met 'OpenAI' als standaard als er geen specifieke engine is opgegeven.
$via = $args['via'] ?? void
unset($args['via'])
$args['model'] ??= $this->model
if ($via) $via = static::engines[strtolower($via)] ?? $via
elseif (isset($args['model'])) $via = static::engines[strtolower(explode(dash, $args['model'])[0])] ?? void
return [$via ?: 'OpenAI', $args]
method

%AI -> chat (...$args):obj

line 22
Deze methode start een chatsessie met de opgegeven AI-engine en argumenten.
[$engine, $args] = $this->resolve(...$args)
return phlo($engine)->chat(...$args)
method

%AI -> stream (...$args):Generator

line 26
Stroomt gegevens van een AI-engine met de opgegeven argumenten.
[$engine, $args] = $this->resolve(...$args)
return phlo($engine)->stream(...$args)
method

%AI -> embedding (...$args):array

line 30
Deze functie lost de engine en argumenten op en roept vervolgens de embedding-methode aan op de opgegeven engine met de meegeleverde argumenten.
[$engine, $args] = $this->resolve(...$args)
return phlo($engine)->embedding(...$args)
method

%AI -> vision (...$args):obj|Generator

line 34
Deze functie lost de AI-engine en argumenten op en roept vervolgens de vision-methode van de opgegeven engine aan met de meegeleverde argumenten.
[$engine, $args] = $this->resolve(...$args)
return phlo($engine)->vision(...$args)
method

%AI -> transcribe (...$args):obj

line 38
Transcribeert audio-invoer met behulp van de opgegeven AI-engine en argumenten.
[$engine, $args] = $this->resolve(...$args)
return phlo($engine)->transcribe(...$args)
object

%Claude

/phlo/resources/AI/Claude.phlo

Anthropic Claude API

Anthropic has no embedding endpoint, so embedding() quietly goes out through OpenAI and needs that key too. system travels as its own field here rather than as a first message, which context() settles, so the same call works on either engine. vision() fetches an image URL itself and sends it inline as base64, so a large photo becomes a large request.

aiclaudeanthropicchatvisionembeddings
const

Claude :: model

line 11
Definieert een model met de 'claude-opus-4-8' bron, die kan worden gebruikt voor verschillende AI-taken binnen Phlo.
'claude-opus-4-8'
static

Claude :: context (...$args):array

line 13
Initialiseert de context voor Claude door berichten en systeemparameters in te stellen, en zorgt ervoor dat gebruikers- en assistentberichten correct zijn opgemaakt en opgeslagen.
$args['messages'] ??= []
if (isset($args['system'])){
	$args['system'] = [['type' => 'text', 'text' => $args['system']]]
}
if (isset($args['assistant']) && array_push($args['messages'], ['role' => 'assistant', 'content' => $args['assistant']])) unset($args['assistant'])
if (isset($args['user']) && array_push($args['messages'], ['role' => 'user', 'content' => $args['user']])) unset($args['user'])
return $args
static

Claude :: tool ($tool):array

line 23
Dit maakt een associatieve array aan met de naam en beschrijving van een tool, samen met het invoerschema, dat de eigenschappen en vereiste argumenten voor de tool definieert.
[
	'name' => $tool->name,
	'description' => $tool->desc,
	'input_schema' => [
		'type' => 'object',
		'properties' => loop($tool->args, fn($data, $arg) => array_filter($data, fn($key) => in_array($key, ['type', 'enum', 'description']), ARRAY_FILTER_USE_KEY)),
		'required' => array_keys($tool->args),
	],
]
method

%Claude -> embedding ($input, $model = 'text-embedding-3-small'):array

line 33
Genereert een embedding voor de gegeven invoer met behulp van het opgegeven model, standaard 'text-embedding-3-small'.
%OpenAI->embedding($input, $model)
method

%Claude -> vision ($text, $image, $stream = false, ...$args):obj|Generator

line 35
Deze functie stuurt een tekst en een afbeelding naar een visiemodel, met de optie om de reactie te streamen of deze in een chatformaat terug te geven.
$data = is_string($image) && str_starts_with($image, 'http') ? file_get_contents($image) : $image
$messages = [['role' => 'user', 'content' => [['type' => 'text', 'text' => $text], ['type' => 'image', 'source' => ['type' => 'base64', 'media_type' => 'image/jpeg', 'data' => base64_encode($data)]]]]]
if ($stream) return $this->stream(...$args, messages: $messages)
else return $this->chat(...$args, messages: $messages)
method

%Claude -> chat (...$args):obj

line 42
Deze functie communiceert met de Claude API om een chatverzoek te verzenden en verwerkt de reactie, waarbij een object wordt geretourneerd met het antwoord, modelinformatie, tokengebruik en eventuele gebruikte tools tijdens de interactie.
$args['model'] ??= static::model
$args['max_tokens'] ??= 4096
$token = $args['token'] ?? null
unset($args['token'])
$args = static::context(...$args)
$res = $this->request('messages', token: $token, POST: $args)
$return = new obj(answer: void, model: $res->model, finish: $res->stop_reason, tokens: ($res->usage->input_tokens ?? 0) + ($res->usage->output_tokens ?? 0), tokens_in: $res->usage->input_tokens ?? 0, tokens_out: $res->usage->output_tokens ?? 0)
$tools = []
foreach ($res->content AS $block){
	if ($block->type === 'text') $return->answer = $block->text
	elseif ($block->type === 'tool_use') $tools[] = new obj(name: $block->name, args: (array)$block->input)
}
if ($tools) $return->tools = $tools
return $return
method

%Claude -> parseSSE (string $url, array $headers, array $payload):Generator

line 59
$json = json_encode($payload, jsonFlat)
$ctx = stream_context_create(['http' => ['method' => 'POST', 'header' => implode(nl, [...$headers, 'Content-Type: application/json', 'Content-Length: '.strlen($json)]), 'content' => $json, 'timeout' => 300, 'ignore_errors' => true]])
$stream = fopen($url, 'r', false, $ctx)
$stream || error('SSE connection failed')
$status = (int)explode(space, $http_response_header[0] ?? 'HTTP/1.1 200')[1]
if ($status >= 400){
	$err = json_decode((string)stream_get_contents($stream))
	fclose($stream)
	error('Claude error '.$status.': '.($err->error->message ?? 'unknown'))
}
$finish = null
$usage = null
while (!feof($stream)){
	$line = fgets($stream)
	if ($line === false) break
	$line = rtrim($line, nl)
	if (!str_starts_with($line, 'data:')) continue
	$data = ltrim(substr($line, 5))
	if ($data === void) continue
	$p = json_decode($data)
	if (!$p) continue
	if (isset($p->error)) error('Claude stream error: '.$p->error->message)
	if (($p->type ?? null) === 'message_delta'){
		$finish = $p->delta->stop_reason ?? $finish
		if (isset($p->usage)) $usage = $p->usage
	}
	if (($p->type ?? null) === 'content_block_delta' && ($p->delta->type ?? null) === 'text_delta' && isset($p->delta->text)) yield obj(text: $p->delta->text)
}
fclose($stream)
yield obj(done: true, finish: $finish, tokens_in: $usage?->input_tokens, tokens_out: $usage?->output_tokens)
method

%Claude -> stream (...$args):Generator

line 91
Streame berichten van de Claude API met behulp van Server-Sent Events (SSE), waardoor real-time interactie met het model mogelijk is.
%res->streaming = true
$args['model'] ??= static::model
$args['max_tokens'] ??= 4096
$token = $args['token'] ?? null
unset($args['token'], $args['cb'])
$args = static::context(...$args)
$args['stream'] = true
if ($token) $headers = ['anthropic-version: 2023-06-01', 'anthropic-beta: oauth-2025-04-20', 'Authorization: Bearer '.$token]
else $headers = ['anthropic-version: 2023-06-01', 'x-api-key: '.%creds->Claude]
return $this->parseSSE('https://api.anthropic.com/v1/messages', $headers, $args)
method

%Claude -> request ($uri, ...$args)

line 104
Verstuurt een verzoek naar de Claude API met de opgegeven URI en argumenten, behandelt authenticatie met een token of API-sleutel, en retourneert de gedecodeerde JSON-respons.
$token = $args['token'] ?? null
if ($token) $headers = ['anthropic-version: 2023-06-01', 'anthropic-beta: oauth-2025-04-20', 'Authorization: Bearer '.$token]
else $headers = ['anthropic-version: 2023-06-01', 'x-api-key: '.%creds->Claude]
$res = json_decode(AI::http("https://api.anthropic.com/v1/$uri", $headers, true, $args['POST'] ?? null))
if (isset($res->error)) error('Claude Request error: '.$res->error->message)
return $res
object

%DeepSeek

/phlo/resources/AI/DeepSeek.phlo

DeepSeek API (OpenAI-compatible, extends OpenAI)

OpenAI-compatible, so it inherits the whole OpenAI resource and only swaps endpoint, model and credentials; anything that works there works here unless DeepSeek itself lacks it. Embeddings are such a gap: they are routed to OpenAI, so that key has to be present as well.

aideepseekchatembeddings
const

DeepSeek :: model

line 12
DeepSeek::model is een component die de creatie en het beheer van modellen binnen het DeepSeek-framework vergemakkelijkt, waardoor efficiënte gegevensverwerking en interactie mogelijk is.
'deepseek-chat'
const

DeepSeek :: endpoint

line 13
Definieert de eindpunt-URL voor toegang tot de DeepSeek API versie 1.
'https://api.deepseek.com/v1/'
const

DeepSeek :: cred

line 14
DeepSeek::cred haalt inloggegevens op voor toegang tot bronnen binnen het DeepSeek-framework.
'DeepSeek'
const

DeepSeek :: label

line 15
DeepSeek::label wordt gebruikt om een label te definiëren voor een DeepSeek-resource, wat zorgt voor betere organisatie en identificatie binnen het systeem.
'DeepSeek'
method

%DeepSeek -> embedding ($input, $model = 'text-embedding-3-small'):array

line 17
Genereert een embedding voor de gegeven invoer met behulp van het opgegeven model, standaard ingesteld op 'text-embedding-3-small'.
%OpenAI->embedding($input, $model)
object

%Gemini

/phlo/resources/AI/Gemini.phlo

Google Gemini API

Google puts the model in the path rather than in the body, so a wrong model name reads as a wrong URL. Its embeddings come from text-embedding-004 with a different vector length than OpenAI's, so a collection filled by one engine cannot be searched with the other.

aigeminigooglechatvisionembeddings
const

Gemini :: model

line 11
Maakt een model in het Gemini-framework, waarmee gegevensstructuren kunnen worden gedefinieerd en gemanipuleerd.
'gemini-2.0-flash'
const

Gemini :: endpoint

line 12
Definieert een eindpunt voor toegang tot de Gemini API, waarmee interactie mogelijk is met het opgegeven model op de gegeven URL.
'https://generativelanguage.googleapis.com/v1beta/models/'
static

Gemini :: context (...$args):array

line 14
Gemini::$context verwerkt invoerargumenten om een gestructureerde context voor een gesprek te creëren, waarbij systeem-, assistent- en gebruikersberichten in een inhoudsarray worden georganiseerd.
$args['contents'] ??= []
if (isset($args['system'])){
	$args['systemInstruction'] = ['parts' => [['text' => $args['system']]]]
	unset($args['system'])
}
if (isset($args['assistant']) && array_push($args['contents'], ['role' => 'model', 'parts' => [['text' => $args['assistant']]]])) unset($args['assistant'])
if (isset($args['user']) && array_push($args['contents'], ['role' => 'user', 'parts' => [['text' => $args['user']]]])) unset($args['user'])
return $args
static

Gemini :: tool ($tool):array

line 25
Gemini::$tool haalt de naam en beschrijving van een tool op, samen met de parameters, die type, eigenschappen en vereiste argumenten omvatten.
[
	'name' => $tool->name,
	'description' => $tool->desc,
	'parameters' => [
		'type' => 'object',
		'properties' => loop($tool->args, fn($data, $arg) => array_filter($data, fn($key) => in_array($key, ['type', 'enum', 'description']), ARRAY_FILTER_USE_KEY)),
		'required' => array_keys($tool->args),
	],
]
method

%Gemini -> embedding ($input, $model = 'text-embedding-004'):array

line 35
Genereert embeddings voor de gegeven invoertekst met behulp van het opgegeven model, standaard 'text-embedding-004'.
$this->request($model.':embedContent', POST: ['content' => ['parts' => [['text' => $input]]]])->embedding->values
method

%Gemini -> vision ($text, $image, $stream = false, ...$args):obj|Generator

line 37
Genereert een vision-reactie door tekst en een afbeelding te combineren, met een optionele streamingfunctie voor realtime-uitvoer.
$model = $args['model'] ?? static::model
unset($args['model'])
$contents = [['role' => 'user', 'parts' => [['text' => $text], ['inline_data' => ['mime_type' => 'image/jpeg', 'data' => base64_encode(is_string($image) && str_starts_with($image, 'http') ? file_get_contents($image) : $image)]]]]]
if ($stream) return $this->stream(...$args, model: $model, contents: $contents)
else return $this->chat(...$args, model: $model, contents: $contents)
method

%Gemini -> chat (...$args):obj

line 45
Genereert inhoud op basis van het opgegeven model en argumenten, en retourneert een object dat het gegenereerde antwoord, het gebruikte model, de reden voor beëindiging en details over het tokenverbruik bevat.
$model = $args['model'] ?? static::model
unset($args['model'])
$args = static::context(...$args)
$res = $this->request($model.':generateContent', POST: $args)
$return = new obj(answer: void, model: $model, finish: $res->candidates[0]->finishReason ?? void, tokens: ($res->usageMetadata->promptTokenCount ?? 0) + ($res->usageMetadata->candidatesTokenCount ?? 0), tokens_in: $res->usageMetadata->promptTokenCount ?? 0, tokens_out: $res->usageMetadata->candidatesTokenCount ?? 0)
$tools = []
foreach ($res->candidates[0]->content->parts ?? [] AS $part){
	if (isset($part->text)) $return->answer = $part->text
	elseif (isset($part->functionCall)) $tools[] = new obj(name: $part->functionCall->name, args: (array)$part->functionCall->args)
}
if ($tools) $return->tools = $tools
return $return
method

%Gemini -> parseSSE (string $url, array $headers, array $payload):Generator

line 60
$json = json_encode($payload, jsonFlat)
$ctx = stream_context_create(['http' => ['method' => 'POST', 'header' => implode(nl, [...$headers, 'Content-Type: application/json', 'Content-Length: '.strlen($json)]), 'content' => $json, 'timeout' => 300, 'ignore_errors' => true]])
$stream = fopen($url, 'r', false, $ctx)
$stream || error('SSE connection failed')
$status = (int)explode(space, $http_response_header[0] ?? 'HTTP/1.1 200')[1]
if ($status >= 400){
	$err = json_decode((string)stream_get_contents($stream))
	fclose($stream)
	error('Gemini error '.$status.': '.($err->error->message ?? 'unknown'))
}
$finish = null
$usage = null
while (!feof($stream)){
	$line = fgets($stream)
	if ($line === false) break
	$line = rtrim($line, nl)
	if (!str_starts_with($line, 'data:')) continue
	$data = ltrim(substr($line, 5))
	if ($data === void) continue
	$p = json_decode($data)
	if (!$p) continue
	if (isset($p->error)) error('Gemini stream error: '.$p->error->message)
	if (isset($p->usageMetadata)) $usage = $p->usageMetadata
	if ($p->candidates[0]->finishReason ?? null) $finish = $p->candidates[0]->finishReason
	$text = $p->candidates[0]->content->parts[0]->text ?? null
	if (!is_null($text)) yield obj(text: $text)
}
fclose($stream)
yield obj(done: true, finish: $finish, tokens_in: $usage?->promptTokenCount, tokens_out: $usage?->candidatesTokenCount)
method

%Gemini -> stream (...$args):Generator

line 91
Schakelt streaming in voor het opgegeven model in Gemini, bereidt de benodigde argumenten voor en retourneert een geparsed Server-Sent Events antwoord.
%res->streaming = true
$model = $args['model'] ?? static::model
unset($args['model'], $args['cb'])
$args = static::context(...$args)
return $this->parseSSE(static::endpoint.$model.':streamGenerateContent?alt=sse', ['x-goog-api-key: '.%creds->Gemini], $args)
method

%Gemini -> request ($path, ...$args)

line 99
Verzendt een verzoek naar de Gemini API op het opgegeven pad met optionele argumenten, behandelt fouten en retourneert de gedecodeerde JSON-respons.
$res = json_decode(AI::http(static::endpoint.$path, ['x-goog-api-key: '.%creds->Gemini], true, $args['POST'] ?? null))
if (isset($res->error)) error('Gemini Request error: '.$res->error->message)
return $res
object

%Grok

/phlo/resources/AI/Grok.phlo

xAI Grok API (OpenAI-compatible, extends OpenAI)

OpenAI-compatible, so it inherits the whole OpenAI resource and only swaps endpoint, model and credentials. Embeddings are not part of the deal and go out through OpenAI, so that key has to be present as well.

aigrokxaichatvisionembeddings
const

Grok :: model

line 12
Grok::model is een component in het Grok-framework die de creatie en het beheer van datamodellen vergemakkelijkt, waardoor eenvoudige interactie met databases en ORM-functionaliteit mogelijk is.
'grok-4'
const

Grok :: endpoint

line 13
Definieert een eindpunt voor het doen van API-aanvragen naar de opgegeven URL.
'https://api.x.ai/v1/'
const

Grok :: cred

line 14
Grok::cred is een module die functies voor het beheer van inloggegevens biedt binnen het Grok-framework.
'Grok'
const

Grok :: label

line 15
Maakt een label voor een Grok-patroon, waardoor betere organisatie en identificatie van patronen in je code mogelijk is.
'Grok'
method

%Grok -> embedding ($input, $model = 'text-embedding-3-small'):array

line 17
Genereert een embedding voor de gegeven invoer met behulp van het opgegeven model, standaard ingesteld op 'text-embedding-3-small'.
%OpenAI->embedding($input, $model)
object

%OpenAI

/phlo/resources/AI/OpenAI.phlo

Basic OpenAI functions

Write a conversation as system, user and assistant instead of assembling messages yourself; context() folds them into the right order. Each answer carries tokens_in and tokens_out, so a run can be metered or capped without reading the raw response. A refused request is raised as an error rather than returned, which is the opposite of how the connectors behave, so wrap a call you cannot afford to lose. Pass token to use a key other than the configured one.

aiopenaillmchatembeddingsaudiovision
const

OpenAI :: model

line 11
Dit item specificeert het OpenAI-model dat gebruikt moet worden, in dit geval 'gpt-5.4-mini'.
'gpt-5.4-mini'
const

OpenAI :: endpoint

line 12
Definieert de endpoint voor toegang tot de OpenAI API, specifiek de basis-URL voor API-verzoeken.
'https://api.openai.com/v1/'
const

OpenAI :: cred

line 13
Dit item vertegenwoordigt de OpenAI-referentie die wordt gebruikt voor authenticatie en toegang tot OpenAI-diensten.
'OpenAI'
const

OpenAI :: label

line 14
Deze functie wordt gebruikt om gegevens te labelen met behulp van de modellen van OpenAI voor verschillende toepassingen.
'OpenAI'
const

OpenAI :: voices

line 15
OpenAI::voices is een vooraf gedefinieerde lijst van stemopties die beschikbaar zijn voor gebruik in Phlo-toepassingen, waaronder 'alloy', 'echo', 'fable', 'onyx', 'nova' en 'shimmer'.
['alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer']
static

OpenAI :: context (...$args):array

line 16
Deze functie initialiseert de 'messages'-array in de context van OpenAI en voegt systeem-, assistent- en gebruikersberichten toe zoals gespecificeerd in de invoerargumenten.
$args['messages'] ??= []
if (isset($args['system']) && array_unshift($args['messages'], ['role' => 'system', 'content' => $args['system']])) unset($args['system'])
if (isset($args['assistant']) && array_push($args['messages'], ['role' => 'assistant', 'content' => $args['assistant']])) unset($args['assistant'])
if (isset($args['user']) && array_push($args['messages'], ['role' => 'user', 'content' => $args['user']])) unset($args['user'])
return $args
static

OpenAI :: tool ($tool):array

line 23
Definieert een functie in OpenAI met gespecificeerde parameters, waaronder type, enum en beschrijving, terwijl strikte validatie van de argumenten wordt afgedwongen.
[
	'type' => 'function',
	'function' => [
		'name' => $tool->name,
		'description' => $tool->desc,
		'parameters' => [
			'type' => 'object',
			'properties' => loop($tool->args, fn($data, $arg) => array_filter($data, fn($key) => in_array($key, ['type', 'enum', 'desc']), ARRAY_FILTER_USE_KEY)),
			'additionalProperties' => false,
			'required' => array_keys($tool->args),
		],
		'strict' => true,
	],
]
method

%OpenAI -> chat (...$args):obj

line 37
Deze functie communiceert met de OpenAI API om chatvoltooiingen te genereren op basis van de opgegeven argumenten, en retourneert een object met de responsdetails zoals het gegenereerde antwoord, het gebruikte model en statistieken over het tokengebruik.
$args['model'] ??= static::model
$token = $args['token'] ?? null
unset($args['token'])
$args = static::context(...$args)
$res = $this->request('chat/completions', token: $token, POST: $args)
$return = new obj(answer: $res->choices[0]->message->content, model: $res->model, finish: $res->choices[0]->finish_reason, tokens: $res->usage->total_tokens, tokens_in: $res->usage->prompt_tokens, tokens_out: $res->usage->completion_tokens)
if (isset($res->choices[0]->message->tool_calls)) $return->tools = array_map(fn($tool) => new obj(name: $tool->function->name, args: json_decode($tool->function->arguments, true)), (array)$res->choices[0]->message->tool_calls)
return $return
method

%OpenAI -> embedding ($input, $model = 'text-embedding-3-small'):array

line 47
Genereert een embedding voor de gegeven invoer met behulp van het opgegeven model van OpenAI.
$this->request('embeddings', POST: ['input' => $input, 'model' => $model])->data[0]->embedding
method

%OpenAI -> parseSSE (string $url, array $headers, array $payload):Generator

line 48
$json = json_encode($payload, jsonFlat)
$ctx = stream_context_create(['http' => ['method' => 'POST', 'header' => implode(nl, [...$headers, 'Content-Type: application/json', 'Content-Length: '.strlen($json)]), 'content' => $json, 'timeout' => 300, 'ignore_errors' => true]])
$stream = fopen($url, 'r', false, $ctx)
$stream || error('SSE connection failed')
$status = (int)explode(space, $http_response_header[0] ?? 'HTTP/1.1 200')[1]
if ($status >= 400){
	$err = json_decode((string)stream_get_contents($stream))
	fclose($stream)
	error(static::label.' error '.$status.': '.($err->error->message ?? 'unknown'))
}
$finish = null
$usage = null
while (!feof($stream)){
	$line = fgets($stream)
	if ($line === false) break
	$line = rtrim($line, nl)
	if (!str_starts_with($line, 'data:')) continue
	$data = ltrim(substr($line, 5))
	if ($data === '[DONE]' || $data === void) continue
	$p = json_decode($data)
	if (!$p) continue
	if (isset($p->error)) error(static::label.' stream error: '.$p->error->message)
	if (isset($p->usage)) $usage = $p->usage
	$text = $p->choices[0]->delta->content ?? null
	if (!is_null($text)) yield obj(text: $text)
	if ($p->choices[0]->finish_reason ?? null) $finish = $p->choices[0]->finish_reason
}
fclose($stream)
yield obj(done: true, finish: $finish, tokens_in: $usage?->prompt_tokens, tokens_out: $usage?->completion_tokens)
method

%OpenAI -> stream (...$args):Generator

line 79
Stroomt reacties van de OpenAI API via Server-Sent Events (SSE), waardoor real-time interactie met het model mogelijk is.
%res->streaming = true
$args['model'] ??= static::model
$token = $args['token'] ?? null
unset($args['token'], $args['cb'])
$args = static::context(...$args)
$args['stream'] = true
$bearer = $token ?? %creds->{static::cred};
return $this->parseSSE(static::endpoint.'chat/completions', ['Authorization: Bearer '.$bearer], $args)
method

%OpenAI -> transcribe ($file, $model = 'whisper-1', ...$args):obj

line 89
Transcribeert audio van een gegeven bestand met behulp van het opgegeven model en retourneert details zoals duur, taal en getranscribeerde tekst.
if (is_string($file)) $file = new CURLFile($file)
elseif (is_a($file, 'file')) $file = $file->curl
$res = $this->request('audio/transcriptions', false, POST: [...$args, 'model' => $model, 'file' => $file, 'response_format' => 'verbose_json'])
return obj (
	model: $model,
	duration: $res->duration,
	lang: $res->language,
	text: $res->text,
)
method

%OpenAI -> vision ($text, $image, $stream = false, ...$args):obj

line 100
Deze functie stuurt een tekst en een afbeelding naar het OpenAI vision-model, met de optie om de reactie te streamen of deze in een chatformaat terug te geven.
$args['model'] ??= static::model
$messages = [['role' => 'user', 'content' => [['type' => 'text', 'text' => $text], ['type' => 'image_url', 'image_url' => ['url' => $image]]]]]
if ($stream) return $this->stream(...$args, messages: $messages)
else return $this->chat(...$args, messages: $messages)
method

%OpenAI -> request ($uri, $JSON = true, $token = null, ...$args)

line 106
Verzendt een verzoek naar de OpenAI API op de opgegeven URI, met de optie om een JSON-payload en een autorisatietoken op te nemen, en retourneert de gedecodeerde reactie.
$bearer = $token ?? %creds->{static::cred};
$res = json_decode(AI::http(static::endpoint.$uri, ['Authorization: Bearer '.$bearer], $JSON, $args['POST'] ?? null))
if (isset($res->error)) error(static::label.' Request error: '.$res->error->message)
return $res

Functions

function

answer($question, ...$options):?string

/phlo/resources/AI/answer.phlo line 11

Simple AI answering helper

For a question with one short answer rather than a conversation: answer('...') gives a bare line and answer('...', 'yes', 'no') forces the reply to be exactly one of the options. Nothing fitting gives null instead of an invented answer, so treat null as a real outcome. It runs at temperature .1, so the same question tends to give the same answer.

aianswerquestionllm
Genereert een kort, direct antwoord op een gegeven vraag, hetzij uit gespecificeerde opties of door een beknopt antwoord te geven zonder extra tekst.
	$prompt = 'You are an AI answer machine. '
	$prompt .= 'You give short, direct answers without repeating the subject. '
	$prompt .= 'You add no explanation, no extra text, and no quotation marks. '
	$prompt .= 'Always answer in the same language as the question.'.lf
	if ($options){
		$prompt .= 'The user asks a question. You choose exactly one of the options below as the answer. '
		$prompt .= 'Your answer matches exactly one of the options, with no extra words or punctuation. '
		$prompt .= 'If none of the options apply, answer with "-".'.lf.lf
		$prompt .= 'Question:'.lf.$question.lf.lf
		$prompt .= 'Options:'.lf
		$prompt .= implode(lf, $options)
	}
	else {
		$prompt .= 'Give a short and precise answer to the question. '
		$prompt .= 'No introduction, no explanation, no list, and no final period.'.lf.lf
		$prompt .= 'Question:'.lf.$question
	}
	$answer = %AI->chat(user: $prompt, temperature: .1)->answer
	return $answer === dash ? null : $answer

Laatst bijgewerkt op 07-08-2026

We gebruiken essentiële cookies om deze site te laten werken. Met uw toestemming gebruiken we ook analytics om de site te verbeteren.