PHP code example of inerba / filament-natural-language-filter

1. Go to this page and download the library: Download inerba/filament-natural-language-filter library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

inerba / filament-natural-language-filter example snippets


use Inerba\FilamentNaturalLanguageFilter\Filters\NaturalLanguageFilter;

public function table(Table $table): Table
{
    return $table
        ->columns([
            // your columns
        ])
        ->filters([
            NaturalLanguageFilter::make()
                ->availableColumns([
                    'id',
                    'name',
                    'email',
                    'status',
                    'created_at',
                    'updated_at'
                ])
                ->availableRelations([
                    'orders',
                    'posts',
                    'profile'
                ])
        ]);
}

// Enable relationship filtering
NaturalLanguageFilter::make()
    ->availableColumns(['name', 'email'])
    ->availableRelations(['orders', 'posts'])
    // Now supports: "users with orders over $100"
    // "posts by active users"
    // "products in electronics category"

// Enable boolean logic (AND/OR operations)
// Supports: "users named john OR email contains gmail"
// "active users AND created after 2023"
// "status is pending AND (amount > 100 OR priority is high)"

// Enable aggregation operations
// Supports: "top 10 users by order count"
// "products with highest sales"
// "users with most posts"

// ProductResource.php
use Inerba\FilamentNaturalLanguageFilter\Filters\NaturalLanguageFilter;

public function table(Table $table): Table
{
    return $table
        ->columns([
            TextColumn::make('name'),
            TextColumn::make('category.name'),
            TextColumn::make('price'),
            TextColumn::make('stock_quantity'),
            TextColumn::make('status'),
            TextColumn::make('created_at'),
        ])
        ->filters([
            NaturalLanguageFilter::make()
                ->availableColumns([
                    'name', 'price', 'stock_quantity', 'status',
                    'created_at', 'updated_at'
                ])
                ->availableRelations(['category', 'reviews', 'orders'])
                ->liveSearch()
        ]);
}

// Now supports queries like:
// - "products in electronics category"
// - "out of stock products"
// - "products with price over $100"
// - "products with more than 10 reviews"
// - "best selling products this month"

// UserResource.php
public function table(Table $table): Table
{
    return $table
        ->columns([
            TextColumn::make('name'),
            TextColumn::make('email'),
            TextColumn::make('status'),
            TextColumn::make('created_at'),
            TextColumn::make('last_login_at'),
        ])
        ->filters([
            NaturalLanguageFilter::make()
                ->availableColumns([
                    'name', 'email', 'status', 'role',
                    'created_at', 'last_login_at', 'email_verified_at'
                ])
                ->availableRelations(['orders', 'posts', 'profile', 'subscriptions'])
                ->submitSearch()
        ]);
}

// Supports queries like:
// - "active users with gmail email"
// - "users who haven't logged in this month"
// - "premium subscribers with orders over $500"
// - "users created this week AND verified"

// PostResource.php
public function table(Table $table): Table
{
    return $table
        ->columns([
            TextColumn::make('title'),
            TextColumn::make('author.name'),
            TextColumn::make('status'),
            TextColumn::make('published_at'),
            TextColumn::make('views_count'),
        ])
        ->filters([
            NaturalLanguageFilter::make()
                ->availableColumns([
                    'title', 'content', 'status', 'views_count',
                    'created_at', 'published_at'
                ])
                ->availableRelations(['author', 'comments', 'tags', 'category'])
                ->liveSearch()
        ]);
}

// Supports queries like:
// - "published posts by john"
// - "posts with more than 100 views"
// - "draft posts created this week"
// - "posts with comments from verified users"

// OrderResource.php
public function table(Table $table): Table
{
    return $table
        ->columns([
            TextColumn::make('order_number'),
            TextColumn::make('customer.name'),
            TextColumn::make('status'),
            TextColumn::make('total_amount'),
            TextColumn::make('created_at'),
        ])
        ->filters([
            NaturalLanguageFilter::make()
                ->availableColumns([
                    'order_number', 'status', 'total_amount',
                    'created_at', 'shipped_at', 'delivered_at'
                ])
                ->availableRelations(['customer', 'items', 'shipping_address'])
                ->submitSearch()
        ]);
}

// Supports queries like:
// - "orders over $1000"
// - "pending orders from premium customers"
// - "orders shipped this week"
// - "orders with more than 5 items"

// Map natural language terms to database columns
NaturalLanguageFilter::make()
    ->availableColumns(['name', 'email', 'status'])
    ->columnMappings([
        'user' => 'name',
        'email address' => 'email',
        'active' => 'status',
        'inactive' => 'status',
        'created' => 'created_at',
        'updated' => 'updated_at'
    ])

// For large datasets, use submit mode
NaturalLanguageFilter::make()
    ->availableColumns(['name', 'email', 'status'])
    ->submitSearch() // Reduces API calls
    ->availableRelations(['orders']) // Limit relationships

// The filter automatically detects and handles multiple languages
// No additional configuration needed!

// English: "active users"
// Spanish: "usuarios activos"
// French: "utilisateurs actifs"
// German: "aktive benutzer"
// Arabic: "المستخدمون النشطون"

// Extend the filter for custom behavior
class CustomNaturalLanguageFilter extends NaturalLanguageFilter
{
    protected function applyFilter(Builder $query, array $filter): void
    {
        // Add custom logic before applying filter
        if ($filter['column'] === 'status' && $filter['value'] === 'active') {
            // Custom logic for active status
            $query->where('status', 'active')
                  ->where('email_verified_at', '!=', null);
            return;
        }

        // Apply standard filter
        parent::applyFilter($query, $filter);
    }
}

public function table(Table $table): Table
{
    return $table
        ->filters([
            // Combine with other Filament filters
            SelectFilter::make('status')
                ->options([
                    'active' => 'Active',
                    'inactive' => 'Inactive',
                ]),

            DateFilter::make('created_at'),

            // Natural language filter works alongside others
            NaturalLanguageFilter::make()
                ->availableColumns(['name', 'email', 'status'])
                ->liveSearch()
        ]);
}

// Use in API endpoints
class UserController extends Controller
{
    public function index(Request $request)
    {
        $query = User::query();

        if ($request->has('natural_query')) {
            $filter = NaturalLanguageFilter::make()
                ->availableColumns(['name', 'email', 'status'])
                ->availableRelations(['orders']);

            $query = $filter->apply($query, [
                'query' => $request->get('natural_query')
            ]);
        }

        return $query->paginate();
    }
}

NaturalLanguageFilter::make()
    ->availableColumns(['name', 'email', 'status'])
    ->submitSearch() // Users press Enter to search

NaturalLanguageFilter::make()
    ->availableColumns(['name', 'email', 'status'])
    ->liveSearch() // Search happens automatically as user types

NaturalLanguageFilter::make()
    ->availableColumns(['name', 'email', 'status'])
    ->searchMode('live') // or 'submit'

// Setup with relationships
NaturalLanguageFilter::make()
    ->availableColumns(['name', 'email', 'status'])
    ->availableRelations(['orders', 'posts', 'profile'])

// config/filament-natural-language-filter.php
return [
    'provider' => 'openai', // 'openai' or 'azure'
    'model' => 'gpt-3.5-turbo', // Model name
    'openai' => [
        'api_key' => env('OPENAI_API_KEY'),
        'max_tokens' => 500,
        'temperature' => 0.1,
    ],
    'azure' => [
        'api_key' => env('AZURE_OPENAI_API_KEY'),
        'endpoint' => env('AZURE_OPENAI_ENDPOINT'),
        'deployment_name' => env('AZURE_OPENAI_DEPLOYMENT_NAME'),
        'api_version' => env('AZURE_OPENAI_API_VERSION', '2024-02-15-preview'),
        'max_tokens' => 500,
        'temperature' => 0.1,
    ],
    'cache' => [
        'enabled' => true,
        'ttl' => 3600, // 1 hour
    ],
];

// Use submit mode instead of live mode
NaturalLanguageFilter::make()
    ->submitSearch() // Reduces API calls

// Limit available columns
->availableColumns(['name', 'email', 'status']) // Only essential columns

// Disable expensive features
FILAMENT_NL_FILTER_RELATIONSHIP_FILTERING=false
FILAMENT_NL_FILTER_AGGREGATION_QUERIES=false

// Add more context to available columns
->availableColumns([
    'name', 'email', 'status', 'created_at',
    'first_name', 'last_name', 'full_name' // Add variations
])

// Enable debug logging
FILAMENT_NL_FILTER_LOGGING=true
FILAMENT_NL_FILTER_LOG_LEVEL=debug

// Ensure relationships are properly defined
// In your model:
public function orders()
{
    return $this->hasMany(Order::class);
}

// In the filter:
->availableRelations(['orders']) // Use exact relationship names

// Use eager loading for relationships
$users = User::with(['orders', 'profile'])
    ->where('status', 'active')
    ->get();

// Limit relationship depth
FILAMENT_NL_FILTER_MAX_RELATION_DEPTH=1

// Configure appropriate cache TTL
'cache' => [
    'enabled' => true,
    'ttl' => 3600, // 1 hour for production
    'prefix' => 'nl_filter',
],

// Test in tinker
php artisan tinker

// Test OpenAI
$processor = app(\Inerba\FilamentNaturalLanguageFilter\Contracts\NaturalLanguageProcessorInterface::class);
$result = $processor->processQuery('active users', ['name', 'status']);
dd($result);

// Override system prompt in config
'custom_prompts' => [
    'system' => 'You are a specialized database query assistant for e-commerce...',
    'user' => 'Convert this e-commerce query: {query}',
],

// Add rate limiting for API calls
'rate_limiting' => [
    'enabled' => true,
    'max_requests_per_minute' => 60,
    'max_requests_per_hour' => 1000,
],

// Add custom query validation
'validation' => [
    'min_length' => 3,
    'max_length' => 500,
    'blocked_words' => ['admin', 'delete', 'drop'],
    'allowed_operators' => ['equals', 'contains', 'greater_than'],
],

// Before (basic)
NaturalLanguageFilter::make()
    ->availableColumns(['name', 'email'])

// After (advanced)
NaturalLanguageFilter::make()
    ->availableColumns(['name', 'email', 'status', 'created_at'])
    ->availableRelations(['orders', 'profile'])
    ->liveSearch()

// Good: Specific, relevant columns
->availableColumns(['name', 'email', 'status', 'created_at'])

// Avoid: Too many columns
->availableColumns(['*']) // Don't do this

// Good: Essential relationships only
->availableRelations(['orders', 'profile'])

// Avoid: Deep relationship chains
->availableRelations(['orders.items.product.category']) // Too deep

// Add performance monitoring
use Illuminate\Support\Facades\Log;

// Log slow queries
if ($query->getQuery()->time > 1000) {
    Log::warning('Slow natural language query', [
        'query' => $queryText,
        'time' => $query->getQuery()->time
    ]);
}

// Test in tinker
php artisan tinker

// Test basic filtering
$filter = NaturalLanguageFilter::make()
    ->availableColumns(['name', 'email', 'status']);

$result = $filter->apply(User::query(), ['query' => 'active users']);
dd($result->toSql());

// Test AI processor directly
$processor = app(\Inerba\FilamentNaturalLanguageFilter\Contracts\NaturalLanguageProcessorInterface::class);

// Test query processing
$filters = $processor->processQuery('users created after 2023', ['name', 'created_at']);
dd($filters);

// Test relationship queries
$filter = NaturalLanguageFilter::make()
    ->availableColumns(['name', 'email'])
    ->availableRelations(['orders']);

$result = $filter->apply(User::query(), ['query' => 'users with orders over $100']);
dd($result->toSql());

// Test in Filament resource
class UserResource extends Resource
{
    public function table(Table $table): Table
    {
        return $table
            ->filters([
                NaturalLanguageFilter::make()
                    ->availableColumns(['name', 'email', 'status'])
                    ->availableRelations(['orders'])
            ]);
    }
}

// Test the actual Filament page
// Visit /admin/users and try natural language queries

// Test with large datasets
$startTime = microtime(true);

$users = User::with(['orders'])
    ->where('status', 'active')
    ->get();

$endTime = microtime(true);
$executionTime = ($endTime - $startTime) * 1000; // Convert to milliseconds

Log::info("Query execution time: {$executionTime}ms");

// Add your new feature code
// Follow existing patterns and add tests

// Create test file
tests/Feature/NewFeatureTest.php

// Write comprehensive tests
public function test_new_feature_works()
{
    // Test implementation
}
bash
php artisan vendor:publish --tag="filament-natural-language-filter-config"
php artisan openai:install
bash
# Check if OpenAI/Azure is configured
php artisan config:show filament-natural-language-filter

# Verify API keys
echo $OPENAI_API_KEY
echo $AZURE_OPENAI_API_KEY