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
此项定义了一个标识符为'gpt-5.4-mini'的AI模型。
'gpt-5.4-mini'
const

AI :: engines

line 12
定义了AI引擎标识符与其各自名称的映射,便于在Phlo应用程序中进行引用和集成。
['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
向指定的URL发送HTTP请求,带有可选的头部、JSON有效负载和POST数据,并允许自定义超时时间。
HTTP($url, $headers, $json, $post, timeout: 300)
method

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

line 14
根据提供的参数解析要使用的AI引擎,如果未指定特定引擎,则默认为'OpenAI'。
$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
此方法使用指定的AI引擎和参数启动聊天会话。
[$engine, $args] = $this->resolve(...$args)
return phlo($engine)->chat(...$args)
method

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

line 26
使用提供的参数从AI引擎流式传输数据。
[$engine, $args] = $this->resolve(...$args)
return phlo($engine)->stream(...$args)
method

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

line 30
该函数解析引擎和参数,然后使用提供的参数调用指定引擎上的 embedding 方法。
[$engine, $args] = $this->resolve(...$args)
return phlo($engine)->embedding(...$args)
method

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

line 34
此函数解析AI引擎和参数,然后使用提供的参数调用指定引擎的vision方法。
[$engine, $args] = $this->resolve(...$args)
return phlo($engine)->vision(...$args)
method

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

line 38
使用指定的AI引擎和参数转录音频输入。
[$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
使用 'claude-opus-4-8' 源定义模型,可用于 Phlo 中的各种 AI 任务。
'claude-opus-4-8'
static

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

line 13
通过设置消息和系统参数来初始化Claude的上下文,确保用户和助手消息被正确格式化和存储。
$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
这构建了一个关联数组,包含工具的名称和描述,以及其输入模式,定义了工具的属性和必需参数。
[
	'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
使用指定的模型为给定输入生成嵌入,默认为'text-embedding-3-small'。
%OpenAI->embedding($input, $model)
method

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

line 35
此函数将文本和图像发送到视觉模型,选项是流式传输响应或以聊天格式返回。
$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
此函数与Claude API交互以发送聊天请求并处理响应,返回一个包含答案、模型信息、令牌使用情况和交互过程中使用的任何工具的对象。
$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
通过服务器发送事件(SSE)从Claude API流式传输消息,实现与模型的实时交互。
%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
使用指定的URI和参数向Claude API发送请求,处理使用令牌或API密钥的身份验证,并返回解码的JSON响应。
$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 是一个组件,便于在 DeepSeek 框架内创建和管理模型,从而实现高效的数据处理和交互。
'deepseek-chat'
const

DeepSeek :: endpoint

line 13
定义访问 DeepSeek API 版本 1 的端点 URL。
'https://api.deepseek.com/v1/'
const

DeepSeek :: cred

line 14
DeepSeek::cred 用于检索访问 DeepSeek 框架内资源的凭据。
'DeepSeek'
const

DeepSeek :: label

line 15
DeepSeek::label用于为DeepSeek资源定义标签,从而在系统内实现更好的组织和识别。
'DeepSeek'
method

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

line 17
使用指定的模型为给定输入生成嵌入,默认模型为'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
在Gemini框架中创建模型,允许定义和操作数据结构。
'gemini-2.0-flash'
const

Gemini :: endpoint

line 12
定义一个用于访问Gemini API的端点,允许与给定URL处的指定模型进行交互。
'https://generativelanguage.googleapis.com/v1beta/models/'
static

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

line 14
Gemini::$context 处理输入参数以构建对话的结构化上下文,将系统、助手和用户消息组织到内容数组中。
$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 获取工具的名称和描述,以及其参数,包括类型、属性和必需的参数。
[
	'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
使用指定的模型为给定的输入文本生成嵌入,默认为'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
通过结合文本和图像生成视觉响应,并提供可选的实时输出流功能。
$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
根据指定的模型和参数生成内容,返回一个对象,其中包括生成的答案、使用的模型、结束原因和令牌使用详情。
$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
为Gemini中指定的模型启用流式传输,准备必要的参数并返回解析后的服务器发送事件响应。
%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
向指定路径的Gemini API发送请求,带有可选参数,处理错误并返回解码的JSON响应。
$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 是Grok框架中的一个组件,便于创建和管理数据模型,从而实现与数据库和ORM功能的轻松交互。
'grok-4'
const

Grok :: endpoint

line 13
定义一个用于向指定URL发起API请求的端点。
'https://api.x.ai/v1/'
const

Grok :: cred

line 14
Grok::cred 是一个模块,提供在 Grok 框架内的凭证管理功能。
'Grok'
const

Grok :: label

line 15
为Grok模式创建一个标签,使您能够更好地组织和识别代码中的模式。
'Grok'
method

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

line 17
使用指定的模型为给定输入生成嵌入,默认为'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
此项指定要使用的OpenAI模型,在这种情况下为'gpt-5.4-mini'。
'gpt-5.4-mini'
const

OpenAI :: endpoint

line 12
定义访问OpenAI API的端点,特别是API请求的基本URL。
'https://api.openai.com/v1/'
const

OpenAI :: cred

line 13
此项表示用于身份验证和访问OpenAI服务的OpenAI凭证。
'OpenAI'
const

OpenAI :: label

line 14
此功能用于使用OpenAI的模型对数据进行标记,以用于各种应用。
'OpenAI'
const

OpenAI :: voices

line 15
OpenAI::voices 是可用于 Phlo 应用程序的预定义语音选项列表,包括 'alloy'、'echo'、'fable'、'onyx'、'nova' 和 'shimmer'。
['alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer']
static

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

line 16
此函数在OpenAI的上下文中初始化'messages'数组,并根据输入参数添加系统、助手和用户消息。
$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
在OpenAI中定义一个具有指定参数的函数,包括类型、枚举和描述,同时强制执行参数的严格验证。
[
	'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
此函数与OpenAI API交互,根据提供的参数生成聊天完成,返回一个包含响应详细信息的对象,例如生成的答案、使用的模型和令牌使用统计信息。
$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
使用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
通过服务器发送事件(SSE)从OpenAI API流式传输响应,允许与模型进行实时交互。
%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
使用指定模型对给定文件中的音频进行转录,返回持续时间、语言和转录文本等详细信息。
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
此函数将文本和图像发送到OpenAI视觉模型,选项是流式传输响应或以聊天格式返回。
$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
向指定的URI发送请求到OpenAI API,可选择包含JSON有效负载和授权令牌,并返回解码后的响应。
$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
生成对给定问题的简短直接回答,可以从指定选项中选择,或提供不带额外文本的简洁回答。
	$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

最近更新于 2026年8月23日

我们使用必要的cookie来使该网站正常工作。在您的许可下,我们还使用分析工具来改善网站。