PHP code example of assistant-engine / filament-assistant

1. Go to this page and download the library: Download assistant-engine/filament-assistant 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/ */

    

assistant-engine / filament-assistant example snippets


use AssistantEngine\Filament\FilamentAssistantPlugin;

class YourPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->plugin(FilamentAssistantPlugin::make());

    }
}

return [
    // Set the default chat driver class. You can override this in your local config.
    'chat_driver' => \AssistantEngine\Filament\Chat\Driver\DefaultChatDriver::class,
    'conversation_resolver' => \AssistantEngine\Filament\Chat\Resolvers\ConversationOptionResolver::class,
    'context_resolver' => \AssistantEngine\Filament\Chat\Resolvers\ContextResolver::class,
    'run_processor' => \AssistantEngine\Filament\Runs\Services\RunProcessorService::class,

    'default_run_queue' => env('DEFAULT_RUN_QUEUE', 'default'),
    'default_assistant' => env('DEFAULT_ASSISTANT_KEY', 'food-delivery'),

    // Assistants configuration: each assistance is identified by a key.
    // Each assistance has a name, a instruction, and a reference to an LLM connection.
    'assistants' => [
        // Example assistance configuration with key "default"
        'default' => [
            'name'              => 'Genius',
            'description'       => 'Your friendly assistant ready to help with any question.',
            'instruction'       => 'You are a helpful assistant.',
            'llm_connection'    => 'openai', // This should correspond to an entry in the llm_connections section.
            'model'             => 'gpt-4o',
            'registry_meta_mode' => false, // See meta mode for details
            // List the tool identifiers to load for this assistant.
            'tools'             => ['weather']
        ],
        'food-delivery' => [
            'name'              => 'Frank',
            'description'       => 'Franks here to help to get you a nice meal',
            'instruction'       => 'Your are Frank a funny person who loves to help customers find the right food.',
            'llm_connection'    => 'openai', // This should correspond to an entry in the llm_connections section.
            'model'             => 'gpt-4o',
            'registry_meta_mode' => false,  // See meta mode for details
            // List the tool identifiers to load for this assistant.
            'tools'             => ['pizza', 'burger']
        ],
    ],

    // LLM Connections configuration: each connection is identified by an identifier.
    // Each connection must burgers);
            },
        ],
    ],

    'button' => [
        'show' => true,
        'options' => [
            'label' => 'Food Delivery',
            'size' => \Filament\Support\Enums\ActionSize::ExtraLarge,
            'color' => \Filament\Support\Colors\Color::Sky,
            'icon' => 'heroicon-o-chat-bubble-bottom-center-text'
        ]
    ],

    // Sidebar configuration
    'sidebar' => [
        // Whether the sidebar is enabled
        'enabled' => true,
        // If set to true, the sidebar will be open by default on load.
        // Using 'open_by_default' instead of 'auto_visible'
        'open_by_default' => false,
        // The width of the sidebar, defined as a CSS dimension.
        // must be an integer
        'width' => 400,
    ],
];


    'tools' => [
        'weather' => [
            'namespace'   => 'weather',
            'description' => 'Function to get informations about the weather.',
            'tool'        => function (\AssistantEngine\Filament\Runs\Models\Run $run) {
                // Now you can access:
                // $thread = $run->thread;
                // $userIdentifier = $thread->user_identifier;
                
                return new \AssistantEngine\OpenFunctions\Core\Examples\WeatherOpenFunction();
            },
        ]
    ]

    'tools' => [
        'weather' => [
            'namespace'   => 'weather',
            'description' => 'Function to get information about the weather.',
            'tool'        => function () {
                return new \AssistantEngine\OpenFunctions\Core\Examples\WeatherOpenFunction();
            },
            'presenter'   => function (\AssistantEngine\Filament\Runs\Models\Run $run) {
                // Return an instance that implements MessageListExtensionInterface, if needed.             
                return new \AssistantEngine\OpenFunctions\Core\Examples\WeatherMessageListExtension();
            },
        ]
    ]

namespace App\Factories;

class FilamentConfigFactory
{
    public static function weather(Run $run)
    {
        return new \AssistantEngine\OpenFunctions\Core\Examples\WeatherOpenFunction();
    }
    
    // ... other methods
}

// config/filament-assistant.php
'tools' => [
    'weather' => [
        'namespace'   => 'weather',
        'description' => 'Function to get informations about the weather.',
        'tool'        => [\App\Factories\FilamentConfigFactory::class, 'weather'],
    ],
    // ... other tools
]
 artisan config:cache

use AssistantEngine\OpenFunctions\Core\Contracts\AbstractOpenFunction;
use AssistantEngine\OpenFunctions\Core\Models\Responses\TextResponseItem;
use AssistantEngine\OpenFunctions\Core\Helpers\FunctionDefinition;
use AssistantEngine\OpenFunctions\Core\Helpers\Parameter;

class HelloWorldOpenFunction extends AbstractOpenFunction
{
    /**
     * Generate function definitions.
     *
     * This method returns a schema that defines the "helloWorld" function.
     */
    public function generateFunctionDefinitions(): array
    {
        // Create a new function definition for helloWorld.
        $functionDef = new FunctionDefinition(
            'helloWorld',
            'Returns a friendly greeting.'
        );

        // In this simple example, no parameters are 

namespace AssistantEngine\Filament\Chat\Resolvers;

use AssistantEngine\Filament\Chat\Contracts\ConversationOptionResolverInterface;
use AssistantEngine\Filament\Chat\Models\ConversationOption;
use Filament\Pages\Page;
use Illuminate\Support\Facades\Config;

class ConversationOptionResolver implements ConversationOptionResolverInterface
{
    public function resolve(Page $page): ?ConversationOption
    {
        $assistantKey = Config::get('filament-assistant.default_assistant');

        if (!$assistantKey) {
            throw new \Exception('assistant-key must be set');
        }

        if (!auth()->check()) {
            return null;
        }

        return new ConversationOption($assistantKey, auth()->user()->id);
    }
}

namespace AssistantEngine\Filament\Chat\Models\ConversationOption;

// Create a new ConversationOption
$options = new ConversationOption($assistantKey, $userId);

// arbitrary data you want to pass to the llm
$options->additionalRunData = [
    'your_context' => 'data'
]; // default []

// add additional tools for the assistant independent of the configuration
$options->additionalTools = ['weather']; // default []

// arbitrary data without any function
$options->metadata = ['foo' => 'bar']; // default [] 

// if true the next time the conversation is recreated
$options->recreate = false; // default false



namespace AssistantEngine\Filament\Chat\Resolvers;

use AssistantEngine\Filament\Chat\Contracts\ContextModelInterface;
use AssistantEngine\Filament\Chat\Contracts\ContextResolverInterface;
use Filament\Pages\Page;
use Filament\Resources\Pages\ListRecords;
use Filament\Resources\Pages\ManageRelatedRecords;
use Filament\Resources\RelationManagers\RelationManager;

class ContextResolver implements ContextResolverInterface
{
    public function resolve(Page $page): array
    {
        $result = [];

        // Collect models directly related to the page's record
        if (isset($page->record)) {
            $this->collectFromRecord($result, $page->record);
        }

        // Collect models for ListRecords page
        if ($page instanceof ListRecords) {
            $this->collectFromListRecordsPage($result, $page);
        }

        // Collect models for ManageRelatedRecords page
        if ($page instanceof ManageRelatedRecords) {
            $this->collectFromManageRelatedRecordsPage($result, $page);
        }

        // Collect models from relation managers
        if (method_exists($page, "getRelationManagers") && !empty($page->getRelationManagers())) {
            $this->collectFromRelationManagers($result, $page);
        }

        return $this->resolveCollectedModels($result);
    }
}



namespace App\Modules\Assistant\Resolvers;

use App\Filament\Resources\ProductResource\Pages\Ideas\IdeaPlanner;
use App\Modules\Product\Models\ProductGoal;
use App\Modules\Product\Models\ProductIdea;
use Filament\Pages\Page;

class ContextResolver extends AssistantEngine\Filament\Chat\Resolvers\ContextResolver
{
    public function resolve(Page $page): array
    {
        $context = parent::resolve($page);

        return match (get_class($page)) {
            IdeaPlanner::class => $this->handleIdeaPlannerPage($page, $context),
            default => $context
        };
    }

    protected function handleIdeaPlannerPage(IdeaPlanner $page, array $context): array
    {
        $context['pageDescription'] = "This page shows a matrix where product goals are the rows and the roadmap phases (now, next, later)"
        . " are the columns. The user can drag and drop the product ideas between different phases and product goals"
        . " The Ideas you find in the context which don't belong to a goal are unassigned";

        $context = array_merge_recursive($context, $this->resolveModels(ProductGoal::class, $page->goals->all()));

        return array_merge_recursive($context, $this->resolveModels(ProductIdea::class, $page->ideas->all()));
    }
}



namespace AssistantEngine\Filament\Chat\Contracts;

interface ContextModelInterface
{
    public static function resolveModels(array $models): array;
}




namespace AssistantEngine\Filament\Chat\Traits;

use AssistantEngine\Filament\Chat\Resolvers\ContextModelResolver;

trait ContextModel
{
    public static function getContextMetaData(): array
    {
        return [
            'schema' => self::class
        ];
    }

    public static function getContextExcludes(): array
    {
        return [];
    }

    public static function resolveModels(array $models): array
    {
        $result = [];
        $result['data'] = null;

        if (count($models) > 0) {
            $result['data'] = ContextModelResolver::collection($models)->resolve();
        }

        $result['meta'] = self::getContextMetaData();

        return $result;
    }
}

namespace AssistantEngine\Filament\Chat\Contracts\ContextModelInterface;

#[Schema(
    schema: "Product",
    properties: [
        new Property(property: "id", type: "integer"),
        new Property(property: "title", type: "string"),
        new Property(property: "description", type: "string"),
        new Property(property: "created_at", type: "string", format: "date-time"),
        new Property(property: "updated_at", type: "string", format: "date-time"),
    ]
)]
class Product extends Model implements ContextModelInterface
{
    use ContextModel;

    protected $fillable = ['title', 'description', 'integration_settings', 'assistant_overwrites'];

    public static function getContextExcludes(): array
    {
        return ['integration_settings'];
    }

    public static function getContextMetaData(): array
    {
        return ['schema' => 'Product'];
    }
}

use AssistantEngine\Filament\Chat\Components\ChatPage;
use AssistantEngine\Filament\FilamentAssistantPlugin;
use Filament\Panels\Panel;
use Filament\Panels\PanelProvider;

class YourPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->plugin(FilamentAssistantPlugin::make())
            // Register the dedicated chat page:
           ->pages([
                \AssistantEngine\Filament\Chat\Pages\AssistantChat::class
            ])
    }
}

use AssistantEngine\Filament\Chat\Components\ChatComponent;

#[On(ChatComponent::EVENT_RUN_FINISHED)]
public function onRunFinished($messages)
{
    // Handle run finished event
}
typescript
// resources/css/filament/admin(theme name)/tailwind.config.js
export default {
    content: [
        './vendor/assistant-engine/filament-assistant/resources/**/*.blade.php',
    ]
};
bash
php artisan migrate
php artisan queue:work

npm run dev
bash
php artisan vendor:publish --tag=filament-assistant-config