pdro-lucas/filament-ai-writer
Composer 安装命令:
composer require pdro-lucas/filament-ai-writer
包简介
AI Writer Action for Filament Forms — supports OpenAI, Claude and Gemini
README 文档
README
untitled.mp4
A reusable Filament Action that adds AI-powered text generation to any form field. Supports Anthropic Claude, OpenAI, and Google Gemini out of the box.
Status: Beta — This package is in active development. APIs may change and issues can occur.
Requirements
- PHP 8.1+
- Laravel 10, 11, or 12
- Filament 4.x
Installation
composer require pdro-lucas/filament-ai-writer
The service provider is auto-discovered by Laravel. No manual registration needed.
Configuration
Add your API key to .env depending on which provider you want to use:
# Anthropic (default) ANTHROPIC_API_KEY=sk-ant-... # OpenAI OPENAI_API_KEY=sk-... # Google Gemini GEMINI_API_KEY=...
To switch providers or customize the model, add the following variables:
AI_WRITER_PROVIDER=anthropic # anthropic | openai | gemini AI_WRITER_MODEL=claude-sonnet-4-20250514 AI_WRITER_MAX_TOKENS=2048 AI_WRITER_CONNECT_TIMEOUT=10 AI_WRITER_TIMEOUT=60 AI_WRITER_RETRY_TIMES=2 AI_WRITER_RETRY_SLEEP_MS=500
If you need to customize the full configuration, publish the config file:
php artisan vendor:publish --tag=filament-ai-writer-config
This creates config/filament-ai-writer.php in your project where you can set per-provider models, API keys, and token limits. Publishing is optional — the package works with just the .env variables.
Usage
Import the action and attach it to any Filament form field using hintAction or suffixAction.
use PdroLucas\FilamentAiWriter\Actions\AiWriterAction;
The action works in two modes: interactive and silent. Interactive mode opens a modal where the user describes what they want. Silent mode reads other fields from the current form as context and generates immediately, with no modal.
Interactive mode
The user clicks the sparkles button, a modal opens with a free-text area, and the AI generates content based on the user input and the configured prompt. The result is injected into the target field.
use Filament\Forms\Components\MarkdownEditor; MarkdownEditor::make('content') ->hintAction( AiWriterAction::make() ->targetField('content') ->prompt(' You are a content writing expert. Write rich Markdown with headers, lists, and well-structured paragraphs. Return ONLY the Markdown content, no explanations. ') ),
use Filament\Forms\Components\Textarea; Textarea::make('excerpt') ->hintAction( AiWriterAction::make('ai_excerpt') ->targetField('excerpt') ->prompt(' Write a concise and engaging summary in 2-3 sentences. Tone: professional but accessible. Return ONLY the summary. ') ),
Silent mode
The user clicks the button and the AI generates immediately, reading the specified context fields from the current form. No modal is shown. A success notification is displayed when generation completes.
If any of the context fields are empty when the button is clicked, the action shows a warning notification listing the missing fields and does not generate.
use Filament\Forms\Components\TextInput; TextInput::make('slug') ->hintAction( AiWriterAction::make('ai_slug') ->targetField('slug') ->contextFields(['title']) ->prompt(' Generate a URL-friendly slug based on the provided title. Return ONLY the slug, lowercase, hyphenated, no special characters. ') ->silent() ),
Silent mode with a select field
Use ->valueMap() when the target field is a select or radio. Pass the same id => name map used in ->options(). The AI receives the available options as context and returns the key of the chosen option.
use Filament\Forms\Components\Select; $categories = Category::all()->pluck('name', 'id'); Select::make('category_id') ->label('Category') ->options($categories) ->hintAction( AiWriterAction::make('ai_category') ->targetField('category_id') ->contextFields(['title', 'body']) ->valueMap($categories->toArray()) ->prompt(' Based on the title and body, choose the most appropriate category. Return ONLY the numeric ID of the chosen category, nothing else. ') ->silent() ),
Silent mode with tags or multi-select
Use ->allowedValues() when the target field is a tags input or multi-select. The AI receives the list of allowed values and must return a JSON array containing only values from that list. Values not present in the list are filtered out before injection.
use Filament\Forms\Components\TagsInput; TagsInput::make('tags') ->hintAction( AiWriterAction::make('ai_tags') ->targetField('tags') ->contextFields(['title', 'body']) ->allowedValues(['laravel', 'filament', 'php', 'api', 'frontend', 'backend']) ->normalizeArrayCase() ->prompt(' Suggest relevant tags based on the title and body. Return ONLY a raw JSON array of strings from the allowed list, no markdown, no explanation. Example: ["laravel","filament","php"] ') ->silent() ),
// Dynamically from the database $tags = Tag::all()->pluck('name')->toArray(); TagsInput::make('tags') ->hintAction( AiWriterAction::make('ai_tags') ->targetField('tags') ->contextFields(['title', 'body']) ->allowedValues($tags) ->normalizeArrayCase() ->prompt(' Suggest relevant tags based on the title and body. Return ONLY a raw JSON array of strings from the allowed list, no markdown, no explanation. Example: ["laravel","filament","php"] ') ->silent() ),
When no ->allowedValues() is provided but the target field still expects an array, use ->expectArray():
TagsInput::make('tags') ->hintAction( AiWriterAction::make('ai_tags') ->targetField('tags') ->contextFields(['title', 'body']) ->expectArray() ->normalizeArrayCase() ->prompt(' Suggest up to five relevant tags based on the title and body. Return ONLY a raw JSON array of strings, no markdown, no explanation. Example: ["laravel","filament","php"] ') ->silent() ),
API reference
AiWriterAction::make(?string $name = null): static
Creates a new action instance. Defaults to 'ai_writer'. If you attach more than one action to the same form, give each a unique name.
->targetField(string $field): static
The name of the form field where the generated text will be injected.
->prompt(string $prompt): static
The system prompt sent to the AI provider. Use this to define tone, format, length constraints, and domain-specific instructions. The more specific the prompt, the better the output.
->contextFields(array $fields): static
An array of field names to read from the current form and pass to the AI as context. Used in silent mode.
->silent(bool $condition = true): static
Enables silent mode. The action generates immediately on click with no modal, using contextFields as input.
->valueMap(array $map): static
An id => name map for select or radio fields. The AI receives the options as context and returns a single key. Use this instead of ->allowedValues() when the field expects a scalar value.
->allowedValues(array $values): static
A flat array of allowed values for tags inputs or multi-selects. The AI must return a JSON array containing only values from this list. Values not present in the list are filtered out before injection.
->expectArray(bool $condition = true): static
Tells the action to parse the AI response as an array even when no ->allowedValues() is defined. Useful for free-form tags where any value is acceptable.
->normalizeArrayCase(bool $condition = true): static
Converts all values in the generated array to lowercase before injection. Useful for tags to ensure consistent casing regardless of what the AI returns.
->beforeGenerate(callable $callback): static
Register a callback that runs before AI generation on this action instance. Return false to cancel generation. Useful for credit checks, permissions, or rate limiting.
use Filament\Forms\Components\TextInput; TextInput::make('meta_description') ->hintAction( AiWriterAction::make() ->targetField('meta_description') ->beforeGenerate(function (): bool { if (auth()->user()->credits <= 0) { return false; } return true; }) ->prompt('Write a meta description.') ),
AiWriterAction::globalBeforeGenerate(callable $callback): void
Register a global callback that runs before every AI generation across all action instances. Typically called in AppServiceProvider::boot(). The instance-level ->beforeGenerate() runs after this global hook.
// AppServiceProvider use PdroLucas\FilamentAiWriter\Actions\AiWriterAction; public function boot(): void { AiWriterAction::globalBeforeGenerate(function (): bool { if (auth()->user()->cannot('use-ai-writer')) { Notification::make() ->warning() ->title('AI writing is not available') ->send(); return false; } return true; }); }
AiTextGenerated event
Dispatched after every successful AI generation. The payload contains:
| Key | Description |
|---|---|
user |
The authenticated user (or null) |
field |
The target field name |
provider |
The AI provider name (e.g. openai) |
model |
The model used for generation |
result |
The raw text returned by the provider |
Listen to this event to debit credits, log usage, or send notifications:
// app/Providers/EventServiceProvider.php use PdroLucas\FilamentAiWriter\Events\AiTextGenerated; protected $listen = [ AiTextGenerated::class => [DebitUserCredits::class], ];
// app/Listeners/DebitUserCredits.php class DebitUserCredits { public function handle(AiTextGenerated $event): void { $user = $event->payload['user']; if ($user === null) { return; } $user->decrement('ai_credits'); } }
Supported providers
| Provider | Default model | Environment variable |
|---|---|---|
| Anthropic | claude-sonnet-4-20250514 |
ANTHROPIC_API_KEY |
| OpenAI | gpt-4o |
OPENAI_API_KEY |
| Gemini | gemini-3.1-flash-lite |
GEMINI_API_KEY |
Package structure
src/
Actions/
AiWriterAction.php # The Filament Action
Contracts/
AiProvider.php # Interface for AI providers
Events/
AiTextGenerated.php # Event dispatched after generation
Providers/
AnthropicProvider.php
OpenAiProvider.php
GeminiProvider.php
FilamentAiWriterServiceProvider.php
config/
filament-ai-writer.php
Extending with a custom provider
Implement the AiProvider contract and rebind it in your AppServiceProvider:
use PdroLucas\FilamentAiWriter\Contracts\AiProvider; public function register(): void { $this->app->bind(AiProvider::class, fn () => new MyCustomProvider()); }
Local development
To use this package in a local project, add a path repository to your project's composer.json:
{
"repositories": [
{
"type": "path",
"url": "../filament-ai-writer"
}
],
"require": {
"pdro-lucas/filament-ai-writer": "@dev"
}
}
Then run:
composer require pdro-lucas/filament-ai-writer @dev
Composer will symlink the local package directory, so any changes you make to the package are reflected immediately in the project.
Contributing
Contributions are welcome! Feel free to open an issue or submit a pull request.
Before contributing, please ensure your changes follow the existing code style and include any necessary updates to documentation.
- Fork the repository
- Create a feature branch (
git checkout -b feat/my-feature) - Commit your changes using conventional commits
- Push to your fork and open a pull request
License
This project is open-sourced under the MIT license.
pdro-lucas/filament-ai-writer 适用场景与选型建议
pdro-lucas/filament-ai-writer 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 504 次下载、GitHub Stars 达 5, 最近一次更新时间为 2026 年 05 月 10 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「laravel」 「ai」 「Gemini」 「filament」 「openai」 「claude」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 pdro-lucas/filament-ai-writer 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 pdro-lucas/filament-ai-writer 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 pdro-lucas/filament-ai-writer 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
AI Agent templates for Laravel development - Skills, Agents, and Workflows for enhanced coding assistance
AI discussion summaries for Flarum with real-time streaming.
Alfabank REST API integration
Database-driven onboarding for Filament: progress checklists and guided spotlight tours, translatable to any locale.
Official Google Gemini provider for the PHP AI SDK.
General-purpose AI token optimization library for PHP — compress context, reduce costs, boost speed.
统计信息
- 总下载量: 504
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 5
- 点击次数: 37
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-05-10