Skip to content

Commit

Permalink
Add prompt finder
Browse files Browse the repository at this point in the history
  • Loading branch information
roxblnfk committed Sep 6, 2024
1 parent 699db9c commit c5663c4
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 17 deletions.
11 changes: 6 additions & 5 deletions src/Bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@

namespace LLM\Assistant;

use LLM\Assistant\Module\Finder\Finder;
use LLM\Assistant\Module\Finder\Internal\FinderImpl;
use LLM\Assistant\Module\Finder\FilesystemFinder;
use LLM\Assistant\Module\Finder\Internal\FilesystemFinderImpl;
use LLM\Assistant\Module\Finder\Internal\PromptFinderImpl;
use LLM\Assistant\Module\Finder\PromptFinder;
use LLM\Assistant\Service\Cache;
use LLM\Assistant\Service\Container;
use LLM\Assistant\Service\Internal\Cache\PsrCache;
use LLM\Assistant\Service\Internal\Container\ContainerImpl;
use LLM\Assistant\Service\Internal\Container\Injection\ConfigLoader;
use LLM\Assistant\Service\Internal\Logger\LoggerImpl;
use LLM\Assistant\Service\Logger;
use Psr\SimpleCache\CacheInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\StyleInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Yiisoft\Cache\File\FileCache;

/**
* Build the container based on the configuration.
Expand Down Expand Up @@ -48,7 +48,8 @@ public function finish(): Container
$c = $this->container;
unset($this->container);

$c->bind(Finder::class, FinderImpl::class);
$c->bind(FilesystemFinder::class, FilesystemFinderImpl::class);
$c->bind(PromptFinder::class, PromptFinderImpl::class);
$c->bind(Cache::class, PsrCache::class);

return $c;
Expand Down
13 changes: 8 additions & 5 deletions src/Command/Run.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace LLM\Assistant\Command;

use LLM\Assistant\Module\Finder\Finder;
use LLM\Assistant\Module\Finder\PromptFinder;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
Expand Down Expand Up @@ -32,11 +32,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int

$this->logger->alert('Assistant is running');

$finder = $this->container->get(Finder::class);
$finder = $this->container->get(PromptFinder::class);

foreach ($finder->files() as $name => $file) {
$this->logger->info($name);
}
#AI test
tr($finder->getNext());

// foreach ($finder->files() as $name => $file) {
// $this->logger->info($name);
// }

return Command::SUCCESS;
}
Expand Down
17 changes: 17 additions & 0 deletions src/Module/Finder/Dto/File.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace LLM\Assistant\Module\Finder\Dto;

final readonly class File
{
/**
* @param list<Prompt> $prompts
*/
public function __construct(
public readonly \SplFileInfo $file,
public readonly string $content,
public readonly array $prompts,
) {}
}
19 changes: 19 additions & 0 deletions src/Module/Finder/Dto/Prompt.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace LLM\Assistant\Module\Finder\Dto;

final readonly class Prompt
{
/**
* @param int<0, max> $start
* @param positive-int $length
* @param non-empty-string $prompt
*/
public function __construct(
public readonly int $start,
public readonly int $length,
public readonly string $prompt,
) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*
* @extends \IteratorAggregate<string, \SplFileInfo>
*/
interface Finder extends \IteratorAggregate
interface FilesystemFinder extends \IteratorAggregate
{
/**
* @return \Traversable<string, \SplFileInfo>
Expand All @@ -18,6 +18,11 @@ public function getIterator(): \Traversable;

public function after(\DateTimeInterface $date): static;

/**
* Sort by modify time, oldest first
*/
public function oldest(): static;

/**
* @return \Traversable<string, \SplFileInfo>
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
namespace LLM\Assistant\Module\Finder\Internal;

use LLM\Assistant\Config\Source;
use LLM\Assistant\Module\Finder\Finder;
use LLM\Assistant\Module\Finder\FilesystemFinder;

final class FinderImpl implements Finder
final class FilesystemFinderImpl implements FilesystemFinder
{
/**
* @param bool|null $sort If true, sort by newest first
*/
public function __construct(
private readonly Source $config,
private ?\DateTimeInterface $after = null,
private ?bool $sort = null,
) {}

public function getIterator(): \Traversable
Expand All @@ -21,7 +25,12 @@ public function getIterator(): \Traversable

public function after(\DateTimeInterface $date): static
{
return new self($this->config, $date);
return new self($this->config, $date, $this->sort);
}

public function oldest(): static
{
return new self($this->config, $this->after, false);
}

public function files(): \Traversable
Expand Down Expand Up @@ -51,9 +60,9 @@ private function finder(): \Symfony\Component\Finder\Finder
$finder->exclude(\array_map($this->directoryToPattern(...), $this->config->excludeDir));
// $finder->exclude($this->config->cacheDir);

if ($this->after !== null) {
$finder->date('> ' . $this->after->format('Y-m-d H:i:s'));
}
$this->after === null or $finder->date('>= ' . $this->after->format('Y-m-d H:i:s'));
// todo direction
$this->sort === null or $finder->sortByModifiedTime();

return $finder;
}
Expand Down
10 changes: 10 additions & 0 deletions src/Module/Finder/Internal/PromptCache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace LLM\Assistant\Module\Finder\Internal;

final class PromptCache
{
public ?\DateTimeInterface $lastScan = null;
}
101 changes: 101 additions & 0 deletions src/Module/Finder/Internal/PromptFinderImpl.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

declare(strict_types=1);

namespace LLM\Assistant\Module\Finder\Internal;

use LLM\Assistant\Module\Finder\Dto\File;
use LLM\Assistant\Module\Finder\Dto\Prompt;
use LLM\Assistant\Module\Finder\FilesystemFinder;
use LLM\Assistant\Module\Finder\PromptFinder;
use LLM\Assistant\Service\Cache;
use LLM\Assistant\Service\Logger;

final class PromptFinderImpl implements PromptFinder
{
private const CACHE_KEY = 'prompt_finder';

private ?PromptCache $lastCache = null;

public function __construct(
private readonly FilesystemFinder $files,
private readonly Cache $cache,
private readonly Logger $logger,
) {}

public function getNext(): ?File
{
$cache = $this->getOrUpdateCache();

// Get last modified files
$files = $cache->lastScan === null
? $this->files->oldest()->files()
: $this->files->after($cache->lastScan)->oldest()->files();

foreach ($files as $file) {
$result = $this->scanFile($file);
if ($result !== null) {
// Update modified time in cache DTO to be saved later
$mtime = $file->getMTime();
$mtime === false or $cache->lastScan = new \DateTimeImmutable('@' . $mtime);

$this->lastCache = $cache;
return $result;
}
}

return null;
}

private function getOrUpdateCache(): PromptCache

Check failure on line 50 in src/Module/Finder/Internal/PromptFinderImpl.php

View workflow job for this annotation

GitHub Actions / psalm (ubuntu-latest, 8.2, locked)

MixedInferredReturnType

src/Module/Finder/Internal/PromptFinderImpl.php:50:42: MixedInferredReturnType: Could not verify return type 'LLM\Assistant\Module\Finder\Internal\PromptCache' for LLM\Assistant\Module\Finder\Internal\PromptFinderImpl::getOrUpdateCache (see https://psalm.dev/047)

Check failure on line 50 in src/Module/Finder/Internal/PromptFinderImpl.php

View workflow job for this annotation

GitHub Actions / psalm (ubuntu-latest, 8.2, locked)

MixedInferredReturnType

src/Module/Finder/Internal/PromptFinderImpl.php:50:42: MixedInferredReturnType: Could not verify return type 'LLM\Assistant\Module\Finder\Internal\PromptCache' for LLM\Assistant\Module\Finder\Internal\PromptFinderImpl::getOrUpdateCache (see https://psalm.dev/047)
{
try {
if ($this->lastCache !== null) {
$this->cache->set(self::CACHE_KEY, $this->lastCache);
return $this->lastCache;
}

return $this->cache->get(self::CACHE_KEY) ?? new PromptCache();

Check failure on line 58 in src/Module/Finder/Internal/PromptFinderImpl.php

View workflow job for this annotation

GitHub Actions / psalm (ubuntu-latest, 8.2, locked)

MixedReturnStatement

src/Module/Finder/Internal/PromptFinderImpl.php:58:20: MixedReturnStatement: Possibly-mixed return value (see https://psalm.dev/138)

Check failure on line 58 in src/Module/Finder/Internal/PromptFinderImpl.php

View workflow job for this annotation

GitHub Actions / psalm (ubuntu-latest, 8.2, locked)

MixedReturnStatement

src/Module/Finder/Internal/PromptFinderImpl.php:58:20: MixedReturnStatement: Could not infer a return type (see https://psalm.dev/138)

Check failure on line 58 in src/Module/Finder/Internal/PromptFinderImpl.php

View workflow job for this annotation

GitHub Actions / psalm (ubuntu-latest, 8.2, locked)

MixedReturnStatement

src/Module/Finder/Internal/PromptFinderImpl.php:58:20: MixedReturnStatement: Possibly-mixed return value (see https://psalm.dev/138)

Check failure on line 58 in src/Module/Finder/Internal/PromptFinderImpl.php

View workflow job for this annotation

GitHub Actions / psalm (ubuntu-latest, 8.2, locked)

MixedReturnStatement

src/Module/Finder/Internal/PromptFinderImpl.php:58:20: MixedReturnStatement: Could not infer a return type (see https://psalm.dev/138)
} catch (\Throwable) {
return new PromptCache();
}
}

private function scanFile(\SplFileInfo $file): ?File
{
$content = \file_get_contents($file->getPathname());
$this->logger->debug(
\sprintf(
'Scanning MT: %s Path: %s',
(new \DateTimeImmutable('@' . (int) $file->getMTime()))->format('Y-m-d H:i:s'),
$file->getPathname(),
),
);

// Find all inline prompts started with "#AI" from a new line
$matches = [];
$result = \preg_match_all(
'/^[ \\t]*#AI[ \\t]+(.+)$/m',
$content,
$matches,
\PREG_OFFSET_CAPTURE,
);

if ($result === 0) {
return null;
}

$prompts = [];
/**
* @var array{
* list<array{non-empty-string, int<0, max>}>,
* list<array{non-empty-string, positive-int}>
* } $matches
*/
foreach ($matches[0] as $key => $match) {
$prompts[] = new Prompt($match[1], \strlen($match[0]), $matches[1][$key][0]);
}

return new File($file, $content, $prompts);
}
}
15 changes: 15 additions & 0 deletions src/Module/Finder/PromptFinder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace LLM\Assistant\Module\Finder;

use LLM\Assistant\Module\Finder\Dto\File;

/**
* Finds new prompts
*/
interface PromptFinder
{
public function getNext(): ?File;
}

0 comments on commit c5663c4

Please sign in to comment.