Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assistant #46

Merged
merged 11 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Modules/LlmDriver/app/BaseClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use LlmLaraHub\LlmDriver\Functions\Chat;
use LlmLaraHub\LlmDriver\Functions\CreateDocument;
use LlmLaraHub\LlmDriver\Functions\CreateEventTool;
use LlmLaraHub\LlmDriver\Functions\CreateTasksTool;
use LlmLaraHub\LlmDriver\Functions\FunctionContract;
use LlmLaraHub\LlmDriver\Functions\FunctionDto;
use LlmLaraHub\LlmDriver\Functions\GatherInfoTool;
Expand All @@ -29,6 +30,8 @@ abstract class BaseClient

protected int $poolSize = 3;

protected ?string $system = null;

protected bool $limitByShowInUi = false;

protected ToolTypes $toolType = ToolTypes::NoFunction;
Expand Down Expand Up @@ -66,6 +69,7 @@ public function getFunctions(): array
new CreateEventTool(),
//new CreateDocument(),
new SatisfyToolsRequired(),
new CreateTasksTool(),
//new Chat(),
]
);
Expand Down Expand Up @@ -117,6 +121,10 @@ public function modifyPayload(array $payload, bool $noTools = false): array
$payload['tools'] = $this->getFunctions();
}

if ($this->system) {
$payload['system'] = $this->system;
}

$payload = $this->addJsonFormat($payload);

return $payload;
Expand Down
35 changes: 23 additions & 12 deletions Modules/LlmDriver/app/ClaudeClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -346,15 +346,31 @@ public function remapMessages(array $messages, bool $userLast = false): array
/**
* Claude needs to not start with a system message
*/
$messages = collect($messages)->transform(function ($item) {
if ($item->role === 'system') {
$item->role = 'assistant';
}
$messages = collect($messages)
->filter(function ($item) {
if ($item->role === 'system') {
$this->system = $item->content;

$item->content = str($item->content)->replaceEnd("\n", '')->trim()->toString();
return false;
}

return $item->toArray();
});
return true;
})
->transform(function (MessageInDto $item) {
/**
* @NOTE
* Claude does not like to end a certain way
*/
$item->content = str(
cleanString($item->content)
)->replaceEnd("\n", '')->trim()->toString();

if (empty($item->content)) {
$item->content = 'See content in thread.';
}

return $item->toArray();
});

/**
* Claude needs me to not use the role tool
Expand All @@ -369,11 +385,6 @@ public function remapMessages(array $messages, bool $userLast = false): array
$toolId = data_get($item, 'tool_id', 'toolu_'.Str::random(32));
$tool = data_get($item, 'tool', 'unknown_tool');
$args = data_get($item, 'args', '{}');
Log::info('Claude Tool Found', [
'tool' => $tool,
'tool_id' => $toolId,
'args' => $args,
]);

$content = $item['content'];

Expand Down
110 changes: 110 additions & 0 deletions Modules/LlmDriver/app/Functions/CreateTasksTool.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php

namespace LlmLaraHub\LlmDriver\Functions;

use App\Models\Message;
use App\Models\Task;
use App\Models\User;
use Illuminate\Support\Facades\Log;
use LlmLaraHub\LlmDriver\Responses\FunctionResponse;

class CreateTasksTool extends FunctionContract
{
protected string $name = 'create_tasks_tool';

protected string $description = 'If the Campaign needs to have tasks created or the users prompt requires it you can use this tool to make multiple tasks';

public bool $showInUi = true;

public array $toolTypes = [
ToolTypes::Source,
ToolTypes::Output,
ToolTypes::Chat,
ToolTypes::ChatCompletion,
];

public function handle(
Message $message): FunctionResponse
{
Log::info('TaskTool called');

$args = $message->args;
foreach (data_get($args, 'tasks', []) as $taskArg) {
$name = data_get($taskArg, 'name', null);
$details = data_get($taskArg, 'details', null);
$due_date = data_get($taskArg, 'due_date', null);
$assistant = data_get($taskArg, 'assistant', false);
$user_id = data_get($taskArg, 'user_id', null);

$project = $message->chat->getChatable();

Task::updateOrCreate([
'name' => $name,
'project_id' => $project->id,
],
[
'details' => $details,
'due_date' => $due_date,
'assistant' => $assistant,
'user_id' => ($user_id !== '' && User::whereId($user_id)->exists()) ? $user_id : null,
]);
}

return FunctionResponse::from([
'content' => json_encode($args),
]);
}

/**
* @return PropertyDto[]
*/
protected function getProperties(): array
{
return [
new PropertyDto(
name: 'tasks',
description: 'Array of task objects',
type: 'array',
required: true,
properties: [
new PropertyDto(
name: 'items',
description: 'Task object',
type: 'object',
required: true,
properties: [
new PropertyDto(
name: 'name',
description: 'Name of the task',
type: 'string',
required: true
),
new PropertyDto(
name: 'details',
description: 'Detailed info of the task',
type: 'string',
required: true
),
new PropertyDto(
name: 'due_date',
description: 'Due date if any format "Y-m-d"',
type: 'string',
required: true
),
new PropertyDto(
name: 'assistant',
description: 'Should the assistant be assigned this true or false',
type: 'string',
),
new PropertyDto(
name: 'user_id',
description: 'User id if assigned to a user',
type: 'string',
),
]
),
]
),
];
}
}
5 changes: 3 additions & 2 deletions Modules/LlmDriver/app/Functions/SearchAndSummarize.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public function handle(
* @TODO @WHY
* Why do I do this system prompt thing?
*/
$assistantMessage = $message->getChat()->addInput(
$message->getChat()->addInput(
message: $contentFlattened,
role: RoleEnum::Assistant,
systemPrompt: $message->getChat()->getChatable()->systemPrompt(),
Expand Down Expand Up @@ -116,7 +116,8 @@ public function handle(
/** @var CompletionResponse $response */
$response = LlmDriverFacade::driver(
$message->getChatable()->getDriver()
)->chat($messages);
)->setToolType(ToolTypes::NoFunction)
->chat($messages);

$this->response = $response->content;

Expand Down
2 changes: 2 additions & 0 deletions Modules/LlmDriver/app/LlmDriverClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace LlmLaraHub\LlmDriver;

use LlmLaraHub\LlmDriver\Functions\CreateTasksTool;
use LlmLaraHub\LlmDriver\Functions\GatherInfoTool;
use LlmLaraHub\LlmDriver\Functions\ReportingTool;
use LlmLaraHub\LlmDriver\Functions\SearchAndSummarize;
Expand Down Expand Up @@ -63,6 +64,7 @@ public function getFunctions(): array
(new StandardsChecker())->getFunction(),
(new ReportingTool())->getFunction(),
(new GatherInfoTool())->getFunction(),
(new CreateTasksTool())->getFunction(),
];
}

Expand Down
5 changes: 5 additions & 0 deletions Modules/LlmDriver/app/LlmServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Support\ServiceProvider;
use LlmLaraHub\LlmDriver\DistanceQuery\DistanceQueryClient;
use LlmLaraHub\LlmDriver\Functions\CreateEventTool;
use LlmLaraHub\LlmDriver\Functions\CreateTasksTool;
use LlmLaraHub\LlmDriver\Functions\GatherInfoTool;
use LlmLaraHub\LlmDriver\Functions\GetWebSiteFromUrlTool;
use LlmLaraHub\LlmDriver\Functions\ReportingTool;
Expand Down Expand Up @@ -98,6 +99,10 @@ public function boot(): void
return new CreateEventTool();
});

$this->app->bind('create_tasks_tool', function () {
return new CreateTasksTool();
});

}

/**
Expand Down
44 changes: 44 additions & 0 deletions Modules/LlmDriver/tests/Feature/CreateTasksToolTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace LlmLaraHub\LlmDriver\Tests\Feature;

use App\Models\Chat;
use App\Models\Message;
use App\Models\Project;
use LlmLaraHub\LlmDriver\Functions\CreateTasksTool;
use Tests\TestCase;

class CreateTasksToolTest extends TestCase
{
/**
* A basic feature test example.
*/
public function test_generates_tasks(): void
{
$project = Project::factory()->create();
$chat = Chat::factory()->create([
'chatable_id' => $project->id,
'chatable_type' => Project::class,
]);

$data = get_fixture('claude_chat_response.json');

$data = data_get($data, 'tool_calls.1.arguments.tasks');

$message = Message::factory()->create([
'chat_id' => $chat->id,
'args' => [
'tasks' => $data,
],
]);

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

(new CreateTasksTool())->handle($message);

$this->assertDatabaseCount('tasks', 5);

$this->assertCount(5, $project->refresh()->tasks);

}
}
2 changes: 2 additions & 0 deletions app/Domains/Chat/UiStatusEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@
enum UiStatusEnum: string
{
case Complete = 'complete';
case InProgress = 'in_progress';
case NotStarted = 'not_started';
}
10 changes: 5 additions & 5 deletions app/Domains/Messages/SearchAndSummarizeChatRepo.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ public function search(

$input = $message->body;

Log::info('[LaraChain] Search and Summarize Default Function', [
'note' => 'Showing input since some system grab the last on the array',
'input' => $input,
]);

$filter = $message->getFilter();

$functionDto = FunctionCallDto::from([
Expand All @@ -47,11 +52,6 @@ public function search(

$message = $this->addToolsToMessage($message, $functionDto);

Log::info('[LaraChain] Search and Summarize Default Function', [
'note' => 'Showing input since some system grab the last on the array',
'input' => $input,
]);

$originalPrompt = $input;

/** @var EmbeddingsResponseDto $embedding */
Expand Down
29 changes: 29 additions & 0 deletions app/Domains/Projects/KickOffProject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace App\Domains\Projects;

use App\Domains\Chat\UiStatusEnum;
use App\Models\Project;
use Facades\App\Domains\Projects\Orchestrate;

class KickOffProject
{
public function handle(Project $project)
{
$chat = $project->chats()->first();

$chat->updateQuietly([
'chat_status' => UiStatusEnum::InProgress,
]);

$chat->messages()->delete();

$project->tasks()->delete();

Orchestrate::handle($chat, $project->content, $project->system_prompt);

$chat->updateQuietly([
'chat_status' => UiStatusEnum::Complete,
]);
}
}
Loading
Loading