Festi AI

TODO

Usage

$prompt = (new Prompt())
    ->addCondition("What is the capital of France?")
    ->addCondition("Please provide a brief explanation.");


$modelId = "gpt-3.5-turbo";
$apiKey = "sk-proj-XXX";
$orgId = "org-XXX";

$config = new AIConfig($modelId, $apiKey, $orgId);

var_dump($config);

$connector = new OpenAiService($config, new OpenAiClient($config));

$connector->connect();

$response = $connector->ask($prompt);
var_dump($response->getAnswer()->getContent());

$config = new AiConfig(
    modelId: 'phi3:latest',
    apiKey: null, // No API key for local setup
    endpoint: 'http://localhost:11434/v1/'
);


$connector = new OllamaService($config, new OllamaClient($config));

$connector->connect();

$response = $connector->ask($prompt);
var_dump($response->getAnswer()->getContent());

Load and save a prompt to a JSON file

$prompt = new Prompt();
$prompt->addCondition("Fix the following code style issues:")
    ->addCondition("- Do not change business logic.")
    ->setTemplate("Here are the conditions:\n{conditions}\n{snippets}")
    ->setRole("Developer")
    ->setResultFormat("Code output only");

// Save to file
$prompt->saveToFile('prompt.json');

// Load from file
$loadedPrompt = Prompt::loadFromFile('prompt.json');
echo $loadedPrompt;

Image Recognition with AI

Example of using AI to extract data from an image.

class BillProcessor
{
    private string $imagesDir;
    private string $processedDir;
    private string $dataDir;
    private OpenAiService $aiService;
    private ImageManager $imageManager;
    private Writer $csvWriter;

    public function __construct(
        private string $projectRoot,
        private array $config
    ) {
        $this->imagesDir = $projectRoot . 'bills/images/';
        $this->processedDir = $projectRoot . 'bills/processed/';
        $this->dataDir = $projectRoot . 'bills/data/';

        $this->initializeServices();
    }

    private function initializeServices(): void
    {
        // Initialize AI Service
        $aiConfig = new AIConfig(
            $this->config['ai']['model_id'] ?? 'gpt-4-vision-preview',
            $this->config['ai']['api_key'],
            $this->config['ai']['org_id']
        );
        $this->aiService = new OpenAiService($aiConfig, new OpenAiClient($aiConfig));
        $this->aiService->connect();

        // Initialize Image Manager
        $this->imageManager = new ImageManager(['driver' => 'gd']);

        // Initialize CSV Writer
        $this->csvWriter = Writer::createFromPath($this->dataDir . 'bills.csv', 'a+');
        $this->csvWriter->insertOne(['id', 'date', 'amount', 'category', 'image_path', 'processed_date']);
    }

    public function processBill(string $imagePath): array
    {
        // Generate unique ID
        $id = uniqid('bill_');

        // Process image
        $image = $this->imageManager->make($imagePath);
        $processedPath = $this->processedDir . $id . '.jpg';
        $image->save($processedPath);

        // Extract data using AI
        $extractedData = $this->extractDataFromImage($imagePath);

        // Save to CSV
        $this->saveToCsv([
            'id' => $id,
            'date' => $extractedData['date'],
            'amount' => $extractedData['amount'],
            'category' => $extractedData['category'],
            'image_path' => $processedPath,
            'processed_date' => date('Y-m-d H:i:s')
        ]);

        return $extractedData;
    }

    private function extractDataFromImage(string $imagePath): array
    {
        $prompt = (new Prompt())
            ->addCondition("Extract the following information from this bill image:")
            ->addCondition("1. Date of the bill")
            ->addCondition("2. Total amount")
            ->addCondition("3. Category (from the following list: " . implode(', ', $GLOBALS['categories']) . ")")
            ->setResultFormat("Return the data in JSON format with keys: date, amount, category")
            ->addFile($imagePath);

        $response = $this->aiService->ask($prompt);
        return json_decode($response->getAnswer()->getContent(), true);
    }

    public function processAllBills(): array
    {
        $results = [];
        $files = glob($this->imagesDir . '*.{jpg,jpeg,png}', GLOB_BRACE);

        foreach ($files as $file) {
            try {
                $result = $this->processBill($file);
                $results[] = [
                    'file' => basename($file),
                    'status' => 'success',
                    'data' => $result
                ];
            } catch (\Exception $e) {
                $results[] = [
                    'file' => basename($file),
                    'status' => 'error',
                    'error' => $e->getMessage()
                ];
            }
        }

        return $results;
    }
}

Usage:

// Initialize processor
$processor = new BillProcessor(
    PROJECT_ROOT,
    [
        'ai' => [
            'model_id' => 'gpt-4-vision-preview',
            'api_key' => $GLOBALS['config']['ai']['api_key'],
            'org_id' => $GLOBALS['config']['ai']['org_id']
        ]
    ]
);

// Process a single bill
$result = $processor->processBill('bills/images/example_bill.jpg');

// Process all bills in directory
$results = $processor->processAllBills();

Ollama

ollama list

ollama restart

ollama run phi3

curl http://localhost:11434/v1/models

curl -X POST http://localhost:11434/v1/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "phi3:latest",
        "prompt": "What is the capital of France?"
    }'