Skip to content

Commit

Permalink
email source working with false option that is great
Browse files Browse the repository at this point in the history
  • Loading branch information
alnutile committed Jul 21, 2024
1 parent 0bfed83 commit 345972a
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 58 deletions.
3 changes: 2 additions & 1 deletion app/Domains/Sources/BaseSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Log;
use LlmLaraHub\LlmDriver\LlmDriverFacade;
use LlmLaraHub\LlmDriver\ToolsHelper;
use LlmLaraHub\TagFunction\Jobs\TagDocumentJob;

abstract class BaseSource
{
use ChatHelperTrait;
use ChatHelperTrait, ToolsHelper;

public string $batchTitle = 'Chunking Source';

Expand Down
107 changes: 54 additions & 53 deletions app/Domains/Sources/EmailSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,72 +53,73 @@ public function handle(Source $source): void

$this->meta_data = $this->mailDto->toArray();

Log::info('[LaraChain] - Running Email Source');

//use the users source prompt to create this next step
//track the results in a chat_id thread
//and as a message?
//then using the source the results will do something with the content
// and then delete the email
// but we can leave it if it returns false?
// still too much coding there how do I let the tool do it.

$prompt = PromptMerge::merge(
['[CONTEXT]'],
[$this->content],
$source->getPrompt()
);

Log::info('[LaraChain] - Running Email Source', [
'prompt' => $prompt,
]);


$chat = $source->chat;

$chat->addInput(
message: $prompt,
role: RoleEnum::User,
show_in_thread: true,
meta_data: MetaDataDto::from([
'driver' => $source->getDriver(),
'source' => $source->title,
]),
);


$results = LlmDriverFacade::driver(
$source->getDriver()
)->completion($prompt);

$chat->addInput(
message: $results->content,
role: RoleEnum::Assistant,
show_in_thread: true,
meta_data: MetaDataDto::from([
'driver' => $source->getDriver(),
'source' => $source->title,
]),
);

//@TODO how to look for false
// surface this "power" into the UI.
// tag or store the fact we checked this emails

$document = Document::updateOrCreate([
'source_id' => $source->id,
'type' => TypesEnum::Email,
'subject' => $this->mailDto->subject,
'collection_id' => $source->collection_id,
], [
'summary' => $results->content,
'meta_data' => $this->mailDto->toArray(),
'original_content' => $this->mailDto->body,
'status_summary' => StatusEnum::Pending,
'status' => StatusEnum::Pending,
]);

Bus::batch([new ChunkDocumentJob($document)])
->name("Processing Email {$this->mailDto->subject}")
->allowFailures()
->dispatch();
if($this->ifNotActionRequired($results->content)) {
Log::info('[LaraChain] - Email Source Skipping', [
'prompt' => $prompt,
]);
} else {

$userMessage = $chat->addInput(
message: $prompt,
role: RoleEnum::User,
show_in_thread: true,
meta_data: MetaDataDto::from([
'driver' => $source->getDriver(),
'source' => $source->title,
]),
);

$document = Document::updateOrCreate([
'source_id' => $source->id,
'type' => TypesEnum::Email,
'subject' => $this->mailDto->subject,
'collection_id' => $source->collection_id,
], [
'summary' => $results->content,
'meta_data' => $this->mailDto->toArray(),
'original_content' => $this->mailDto->body,
'status_summary' => StatusEnum::Pending,
'status' => StatusEnum::Pending,
]);

Bus::batch([new ChunkDocumentJob($document)])
->name("Processing Email {$this->mailDto->subject}")
->allowFailures()
->dispatch();

$assistantMessage = $chat->addInput(
message: $results->content,
role: RoleEnum::Assistant,
show_in_thread: true,
meta_data: MetaDataDto::from([
'driver' => $source->getDriver(),
'source' => $source->title,
]),
);

$this->savePromptHistory(
message: $assistantMessage,
prompt: $prompt);
}

//should we delete the email?
// right now it gets set to seen
// on the MailDto we have options
}
}
15 changes: 15 additions & 0 deletions app/Helpers/ChatHelperTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,19 @@ public function getUserId(Collection $collection): ?int

return $collection->team?->user_id;
}

public function ifNotActionRequired(string $results): bool {
// @NOTE llms sometimes do not return the right
// string for example.
// false becomes false, "false" or "False" etc.

$results = str($results)
->trim()
->lower()
->remove('"')
->remove("'")
->toString();

return $results == "false";
}
}
68 changes: 68 additions & 0 deletions app/Jobs/ChunkDocumentJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,26 @@

namespace App\Jobs;

use App\Helpers\TextChunker;
use App\Models\Document;
use App\Models\DocumentChunk;
use Illuminate\Bus\Batch;
use Illuminate\Bus\Batchable;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Log;
use LlmLaraHub\LlmDriver\LlmDriverFacade;
use LlmLaraHub\TagFunction\Jobs\TagDocumentJob;

/**
* @NOTE
* Only really good for chunking content that can fit in the Original Content
* of a Document model.
*/
class ChunkDocumentJob implements ShouldQueue
{
use Batchable;
Expand All @@ -34,5 +45,62 @@ public function handle(): void
return;
}


Log::info('[LaraChain] - Chunking Document', [
'document' => $this->document->id,
]);

$document = $this->document;

$page_number = 0;

$pageContent = $this->document->original_content;

$size = config('llmdriver.chunking.default_size');

$chunked_chunks = TextChunker::handle($pageContent, $size);

foreach ($chunked_chunks as $chunkSection => $chunkContent) {
$guid = md5($chunkContent);

$DocumentChunk = DocumentChunk::updateOrCreate(
[
'document_id' => $document->id,
'sort_order' => $page_number,
'section_number' => $chunkSection,
],
[
'guid' => $guid,
'content' => to_utf8($chunkContent),
]
);

$chunks[] = [
new VectorlizeDataJob($DocumentChunk),
];
}

$name = sprintf($document->type->name, $document->id);



Bus::batch($chunks)
->name($name)
->allowFailures()
->finally(function (Batch $batch) use ($document) {

Bus::batch([
[
new SummarizeDocumentJob($document),
new TagDocumentJob($document),
new DocumentProcessingCompleteJob($document),
]
])
->name(sprintf("Final Document Steps Document %s id %d", $document->type->name, $document->id))
->allowFailures()
->dispatch();
})
->onQueue(LlmDriverFacade::driver($document->getDriver())->onQueue())
->dispatch();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

<div>
<InputLabel value="Details"/>
<textarea v-model="modelValue.details" class="rounded-none textarea textarea-bordered w-full mb-5"
<textarea v-model="modelValue.details"
rows="20"
class="rounded-none textarea textarea-bordered w-full mb-5"
placeholder="This can assist the LLM to process your messages later."></textarea>
<InputError :message="modelValue.errors.details" />
</div>
Expand Down
45 changes: 45 additions & 0 deletions tests/Feature/EmailSourceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,49 @@ public function tests_creates_chat_and_message()

Bus::assertBatchCount(1);
}


public function test_no_action_required()
{
Bus::fake();
$source = Source::factory()->create([
'slug' => 'test',
'type' => SourceTypeEnum::EmailSource,
]);

LlmDriverFacade::shouldReceive('driver->completion')->once()->andReturn(
CompletionResponse::from([
'content' => 'False',
])
);

$body = <<<'BODY'
Quis ea esse velit id id eu consectetur deserunt exercitation exercitation. Nisi aliqua ipsum fugiat laborum aliquip nostrud eu tempor non cillum Lorem non dolor proident sunt. Irure commodo aliqua reprehenderit deserunt sint irure in excepteur quis eiusmod ullamco aliquip. Dolore tempor ea non ut.Quis ea esse velit id id eu consectetur deserunt exercitation exercitation. Nisi aliqua ipsum fugiat laborum aliquip nostrud eu tempor non cillum Lorem non dolor proident sunt. Irure commodo aliqua reprehenderit deserunt sint irure in excepteur quis eiusmod ullamco aliquip. Dolore tempor ea non ut.
Quis ea esse velit id id eu consectetur deserunt exercitation exercitation. Nisi aliqua ipsum fugiat laborum aliquip nostrud eu tempor non cillum Lorem non dolor proident sunt. Irure commodo aliqua reprehenderit deserunt sint irure in excepteur quis eiusmod ullamco aliquip. Dolore tempor ea non ut.
Quis ea esse velit id id eu consectetur deserunt exercitation exercitation. Nisi aliqua ipsum fugiat laborum aliquip nostrud eu tempor non cillum Lorem non dolor proident sunt. Irure commodo aliqua reprehenderit deserunt sint irure in excepteur quis eiusmod ullamco aliquip. Dolore tempor ea non ut.
Quis ea esse velit id id eu consectetur deserunt exercitation exercitation. Nisi aliqua ipsum fugiat laborum aliquip nostrud eu tempor non cillum Lorem non dolor proident sunt. Irure commodo aliqua reprehenderit deserunt sint irure in excepteur quis eiusmod ullamco aliquip. Dolore tempor ea non ut.
Quis ea esse velit id id eu consectetur deserunt exercitation exercitation. Nisi aliqua ipsum fugiat laborum aliquip nostrud eu tempor non cillum Lorem non dolor proident sunt. Irure commodo aliqua reprehenderit deserunt sint irure in excepteur quis eiusmod ullamco aliquip. Dolore tempor ea non ut.
Quis ea esse velit id id eu consectetur deserunt exercitation exercitation. Nisi aliqua ipsum fugiat laborum aliquip nostrud eu tempor non cillum Lorem non dolor proident sunt. Irure commodo aliqua reprehenderit deserunt sint irure in excepteur quis eiusmod ullamco aliquip. Dolore tempor ea non ut.

BODY;

$dto = MailDto::from([
'to' => '[email protected]',
'from' => '[email protected]',
'subject' => 'This is it',
'header' => 'This is header',
'body' => $body,
]);

$emailSource = new \App\Domains\Sources\EmailSource();
$emailSource->setMailDto($dto)->handle($source);

$this->assertDatabaseCount('documents', 0);
$this->assertDatabaseCount('chats', 1);
$this->assertDatabaseCount('messages', 1);

$this->assertNotNull($source->chat_id);

Bus::assertBatchCount(0);
}
}
21 changes: 18 additions & 3 deletions tests/Feature/Jobs/ChunkDocumentJobTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,32 @@

namespace Tests\Feature\Jobs;

use App\Jobs\ChunkDocumentJob;
use App\Models\Document;
use Illuminate\Support\Facades\Bus;
use Tests\TestCase;

class ChunkDocumentJobTest extends TestCase
{
/**
* A basic feature test example.
*/
public function test_example(): void
public function test_chunking(): void
{
$response = $this->get('/');
Bus::fake();

$response->assertStatus(200);
$document = Document::factory()->create();

$this->assertDatabaseCount('document_chunks', 0);


[$job, $batch] = (new ChunkDocumentJob($document))->withFakeBatch();


$job->handle();

$this->assertDatabaseCount('document_chunks', 1);

Bus::assertBatchCount(1);
}
}

0 comments on commit 345972a

Please sign in to comment.