VOOZH about

URL: https://deepwiki.com/guanguans/ai-commit/5.2-api-based-generators

⇱ API-Based Generators | guanguans/ai-commit | DeepWiki


Loading...
Menu

API-Based Generators

This page covers the five generators that communicate with remote AI APIs over HTTP: OpenAIGenerator, OpenAIChatGenerator, MoonshotGenerator, ErnieBotGenerator, and ErnieBotTurboGenerator. It describes their request construction, streaming response handling, and the HTTP client classes they depend on.

For the base class that all generators share (AbstractGenerator, GeneratorContract, GeneratorManager), see Generator Architecture. For generators that invoke external CLI binaries instead of HTTP APIs, see CLI-Based Generators. For the shared HTTP client layer internals (retry, logging, user-agent), see HTTP Client Layer.


Generator and Client Class Map

Generator-to-client relationships:


Sources: app/Generators/OpenAIGenerator.php1-88 app/Generators/OpenAIChatGenerator.php1-52 app/Generators/MoonshotGenerator.php1-71 app/Generators/ErnieBotGenerator.php1-79 app/Generators/ErnieBotTurboGenerator.php1-31


Generator Overview Table

Driver keyGenerator classClient classAPI endpoint
openaiOpenAIGeneratorOpenAIPOST /v1/completions
openai_chatOpenAIChatGeneratorOpenAIPOST /v1/chat/completions
moonshotMoonshotGeneratorMoonshotPOST /v1/chat/completions
ernie_botErnieBotGeneratorErniePOST rpc/2.0/.../chat/completions
ernie_bot_turboErnieBotTurboGeneratorErniePOST rpc/2.0/.../chat/eb-instant

Sources: app/GeneratorManager.php63-77 app/Clients/OpenAI.php69-100 app/Clients/Moonshot.php62-107 app/Clients/Ernie.php64-76


generate() Call Flow

Sequence: from generate() call to returned string:


Sources: app/Generators/OpenAIGenerator.php56-87 app/Generators/MoonshotGenerator.php36-70 app/Generators/ErnieBotGenerator.php37-77


Streaming vs. Non-Streaming Response Handling

All API-based generators share the same dual-path pattern in generate():

return $messages ?? $this->getCompletionMessages($response);
  • Streaming path (parameters.stream = true): The HTTP client registers a CURLOPT_WRITEFUNCTION curl callback. Each incoming data chunk is passed to the buildWriter() closure, which accumulates content into $messages by reference. When generate() returns, $messages is non-null and is returned directly.
  • Non-streaming path (parameters.stream = false or absent): No CURLOPT_WRITEFUNCTION is set, so $messages remains null. generate() falls back to calling getCompletionMessages($response) on the full HTTP response object.

This also explains how test fakes work: Http::fake() bypasses curl entirely, so $messages is always null during tests, and the response array is parsed instead.

Sources: app/Generators/OpenAIGenerator.php63-66 app/Generators/MoonshotGenerator.php44-47 app/Generators/ErnieBotGenerator.php46-49 app/Clients/OpenAI.php193-220


buildWriter() Implementation

buildWriter() per generator:


OpenAIGenerator::buildWriter() and MoonshotGenerator::buildWriter() both split on PHP_EOL and call AbstractClient::sanitizeData() to strip the data: prefix used in Server-Sent Events. ErnieBotGenerator::buildWriter() does not split lines or call sanitizeData() — the Ernie API delivers raw JSON directly.

Sources: app/Generators/OpenAIGenerator.php77-87 app/Generators/MoonshotGenerator.php58-70 app/Generators/ErnieBotGenerator.php63-72 app/Clients/AbstractClient.php79-85


getCompletionMessages() Response Paths

Each generator extracts text from a different JSON path depending on its API format:

GeneratorJSON path extractedAPI format
OpenAIGeneratorchoices.0.textCompletions API
OpenAIChatGeneratorchoices.0.delta.contentChat completions (streaming chunk)
MoonshotGenerator (stream)choices.0.delta.contentChat completions chunk
MoonshotGenerator (non-stream)choices.0.message.contentChat completions full response
ErnieBotGeneratorresultErnie ERNIE-Bot format

MoonshotGenerator::getCompletionMessages() checks $this->config->get('parameters.stream', false) at runtime to decide which path to use.

Sources: app/Generators/OpenAIGenerator.php69-72 app/Generators/OpenAIChatGenerator.php48-51 app/Generators/MoonshotGenerator.php50-55 app/Generators/ErnieBotGenerator.php74-77


OpenAIGenerator and OpenAIChatGenerator

Both classes reside in app/Generators/OpenAIGenerator.php and app/Generators/OpenAIChatGenerator.php and share the same OpenAI client instance.

OpenAIGenerator targets the legacy text completions endpoint. Its generate() method constructs:

[
 'prompt' => $prompt,
 'user' => Str::uuid()->toString(),
 ...config parameters
]

Then calls $this->openAI->completions($parameters, $this->buildWriter($messages)).

OpenAIChatGenerator overrides generate() to target the chat completions endpoint. Its request body uses the messages array format:

[
 'messages' => [['role' => 'user', 'content' => $prompt]],
 'user' => Str::uuid()->toString(),
 ...config parameters
]

Then calls $this->openAI->chatCompletions($parameters, $this->buildWriter($messages)).

OpenAIChatGenerator also overrides getCompletionMessages() because streaming chat responses use choices.0.delta.content instead of choices.0.text.

Sources: app/Generators/OpenAIGenerator.php56-72 app/Generators/OpenAIChatGenerator.php28-51

OpenAI HTTP Client

app/Clients/OpenAI.php extends AbstractClient.

  • Base URL: https://api.openai.com/v1 (configurable via base_url)
  • Auth: Authorization: Bearer {api_key}
  • completions(): validates and POSTs to completions; parameter rules include model (required), prompt, max_tokens, temperature, stream, user, etc.
  • chatCompletions(): POSTs to chat/completions; rules include model (required), messages (required array), temperature, stream, user, etc.
  • Streaming: When parameters['stream'] === true and a callable $writer is provided, a CURLOPT_WRITEFUNCTION callback is registered via withOptions(['curl' => [...]]). Accumulated $rowData is reconstructed into the response body if the normal body is empty (to preserve the response object for logging/debugging).

Sources: app/Clients/OpenAI.php69-220


MoonshotGenerator

app/Generators/MoonshotGenerator.php extends AbstractGenerator directly.

The generate() method sends:

[
 'messages' => [['role' => 'user', 'content' => $prompt]],
 ...config parameters
]

Note: no user UUID field is sent (unlike OpenAI generators). The Moonshot client is instantiated in the constructor from the generator's config.

getCompletionMessages() has branching logic depending on parameters.stream:

  • Stream mode: choices.0.delta.content
  • Non-stream mode: choices.0.message.content

Sources: app/Generators/MoonshotGenerator.php1-71

Moonshot HTTP Client

app/Clients/Moonshot.php extends AbstractClient.

  • Base URL: https://api.moonshot.cn/v1 (configurable via base_url)
  • Auth: Authorization: Bearer {api_key}
  • chatCompletions(): POSTs to chat/completions; parameter rules: model (required), messages (required), temperature, top_p, n, stream, max_tokens, presence_penalty, frequency_penalty
  • Streaming: Same CURLOPT_WRITEFUNCTION pattern as the OpenAI client

Sources: app/Clients/Moonshot.php62-131


ErnieBotGenerator and ErnieBotTurboGenerator

app/Generators/ErnieBotGenerator.php extends AbstractGenerator. app/Generators/ErnieBotTurboGenerator.php extends ErnieBotGenerator and only overrides completion().

ErnieBotGenerator::generate() builds:

[
 'messages' => [['role' => 'user', 'content' => $prompt]],
 'user_id' => Str::uuid()->toString(),
 ...config parameters
]

It delegates to $this->completion($parameters, $this->buildWriter($messages)), which calls $this->ernie->ernieBot(...).

ErnieBotTurboGenerator overrides only the completion() method to call $this->ernie->ernieBotTurbo(...) instead. All other logic (request construction, buildWriter, getCompletionMessages) is inherited from ErnieBotGenerator.

getCompletionMessages() extracts result from the response (not choices.*.text as in OpenAI-style APIs).

Sources: app/Generators/ErnieBotGenerator.php1-79 app/Generators/ErnieBotTurboGenerator.php1-31

Ernie HTTP Client

app/Clients/Ernie.php extends AbstractClient.

  • Base URL: https://aip.baidubce.com (configurable via base_url)
  • Auth: OAuth 2.0 — requires both api_key and secret_key; the client fetches an access token via oauthToken() on the first request, caches it in a static $accessToken property, and appends it as a query parameter (access_token=...) on all subsequent API calls
  • ernieBot(): POSTs to rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions
  • ernieBotTurbo(): POSTs to rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant
  • Parameter rules: messages (required), temperature (0–1, narrower than OpenAI's 0–2), top_p, penalty_score (1–2), stream, user_id
  • Error handling: The Ernie API can return HTTP 200 with an error_code field in the body. After throw(), the client explicitly checks for error_code and raises a RequestException in that case
  • Streaming: The CURLOPT_WRITEFUNCTION passes the data through sanitizeData() (stripping data: prefix) before accumulating and calling $writer

Sources: app/Clients/Ernie.php64-169


OAuth Token Lifecycle (Ernie)


Sources: app/Clients/Ernie.php109-169


Configuration Keys per Generator

Each generator reads its configuration from the ai-commit.generators.<driver> block. Below are the relevant keys:

KeyApplies toPurpose
api_keyAllAuthentication credential (Bearer token or OAuth client ID)
secret_keyernie_bot, ernie_bot_turboOAuth client secret
base_urlAllOverrides the default API base URL
parameters.modelopenai, openai_chat, moonshotModel name passed in request body
parameters.streamAllEnables SSE streaming mode
parameters.max_tokensopenai, openai_chat, moonshotToken limit
parameters.temperatureAllSampling temperature
http_optionsAllPassed through to Guzzle (timeouts, proxies, etc.)
retry.timesAllRetry interval array (Fibonacci by default)

Sources: app/Clients/OpenAI.php175-188 app/Clients/Moonshot.php118-130 app/Clients/Ernie.php96-107 app/Clients/AbstractClient.php249-280


Request Parameter Construction Summary


Sources: app/Generators/OpenAIGenerator.php58-62 app/Generators/OpenAIChatGenerator.php30-35 app/Generators/MoonshotGenerator.php39-43 app/Generators/ErnieBotGenerator.php39-44