LaraVEL ile Claude CLI Entegre Etmek
Bu yazıda, Laravel uygulamanızla Claude CLI’yi nasıl entegre edebileceğinizi açıklayacağım. Amacımız, API maliyetlerini azaltmak ve daha sürdürülebilir bir çözüm sunmaktır.
Prism ile Sağlayıcı Gereksinimleri
prism, bir sağlayıcıdan belirli yöntemleri uygulamasını bekler. Örnek olarak, sadece iki metod gereklidir:
text(TextRequest $request): TextResponsestructured(StructuredRequest $request): StructuredResponse
Diğer özellikleri uygulamanıza gerek yoktur. Örneğin, gömme, görsel veya akış gibi işlemler bu örnekte dışarıda bırakılmıştır.
CLI Sözleşmesi
Öncelikle, trafiği test etmek için şu komutu çalıştırın:
echo "say hi" | claude -p --output-format json --model claude-haiku-4-5Bu komut, aşağıdaki gibi bir JSON nesnesi dönecektir:
{
"is_error": false,
"result": "hi!",
"session_id": "abc-123",
"model": "claude-haiku-4-5",
"usage": {
"input_tokens": 12,
"output_tokens": 3,
"cache_read_input_tokens": 0
}
}Provider Sınıfı
Aşağıda, app/Prism/ClaudeCli/ClaudeCliProvider.php dosyasında yer alan provider sınıfı verilmiştir:
final class ClaudeCliProvider extends Provider
{
public function __construct(
private readonly string $binary,
private readonly ?string $oauthToken,
private readonly string $defaultModel,
private readonly int $timeout,
) {}
public function text(TextRequest $request): TextResponse
{
$envelope = $this->invoke(
$this->resolveModel($request->model()),
$this->composeSystemPrompt($request->systemPrompts()),
$this->composeUserPrompt($request->prompt(), $request->messages()),
$this->timeoutFor($request->clientOptions()),
);
return new TextResponse(
steps: new Collection,
text: $this->resultText($envelope),
finishReason: FinishReason::Stop,
toolCalls: [],
toolResults: [],
usage: $this->usage($envelope),
meta: $this->meta($envelope),
messages: new Collection,
);
}
}
Shell Çalıştırma ve Güvenlik
CLI’yi çalıştırırken dikkat etmeniz gereken birkaç nokta vardır:
private function invoke(string $model, string $systemPrompt, string $userPrompt, int $timeout): array
{
$command = [$this->binary, '-p', '--output-format', 'json', '--model', $model];
if (trim($systemPrompt) !== '') {
$command[] = '--append-system-prompt';
$command[] = $systemPrompt;
}
$result = Process::timeout($timeout)
->path(sys_get_temp_dir())
->env($this->processEnv())
->input($userPrompt)
->run($command);
if ($result->failed()) {
throw PrismException::providerResponseError(
'claude-cli exited with code '.$result->exitCode().': '.trim($result->errorOutput()),
);
}
$envelope = json_decode($result->output(), true);
if (! is_array($envelope)) {
throw PrismException::providerResponseError('claude-cli returned non-JSON output: '.$result->output());
}
if (($envelope['is_error'] ?? false) === true) {
throw PrismException::providerResponseError('claude-cli reported an error: '.($envelope['result'] ?? 'unknown'));
}
return $envelope;
}
Burada dikkat edilmesi gereken noktalar:
- Kullanıcı girişi
stdinüzerinden alınmalıdır. - Geçici dizin kullanılmalıdır; böylece uygulama talimatlarınız dışarıda kalır.
is_errorkontrol edilmelidir. CLI, hata olmadığında bile hata mesajı dönebilir.
Datayı Yapılandırılmış Çıktı Olarak Almak
Provider’ın yapılandırıldığından emin olmak için aşağıdaki gibi bir yöntem kullanabilirsiniz:
public function structured(StructuredRequest $request): StructuredResponse
{
$userPrompt = $this->composeUserPrompt($request->prompt(), $request->messages())
.$this->schemaInstruction($request->schema()->toArray());
$envelope = $this->invoke(/* ... */);
$text = $this->resultText($envelope);
return new StructuredResponse(
steps: new Collection,
text: $text,
structured: $this->decodeJson($text),
finishReason: FinishReason::Stop,
usage: $this->usage($envelope),
meta: $this->meta($envelope),
);
}
Provider’ı Kaydetmek
Provider’ı Service Provider içinde kaydedin:
public function boot(): void
{
$this->app->make(PrismManager::class)->extend('claude-cli', fn (): ClaudeCliProvider => new ClaudeCliProvider(
binary: config('prism.claude_cli.binary'),
oauthToken: config('prism.claude_cli.oauth_token'),
defaultModel: config('prism.claude_cli.model'),
timeout: (int) config('prism.claude_cli.timeout'),
));
}
Sonuç
Sonuç olarak, API maliyetlerini sıfıra düşürmek için Claude CLI’yi kullanmak, küçük ve orta ölçekli projelerde faydalı bir yöntemdir. Ancak, geniş ölçekli uygulamalar için işlem başlatmanın yüksek maliyetler doğurabileceği unutulmamalıdır.
Kaynak: Orijinal Makale


