Skip to content

Commit

Permalink
this should get claude back into the game
Browse files Browse the repository at this point in the history
  • Loading branch information
alnutile committed Apr 17, 2024
1 parent 37b9840 commit 363a63a
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 38 deletions.
12 changes: 12 additions & 0 deletions Modules/LlmDriver/app/BaseClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,16 @@ public function getFunctions(): array
];
})->toArray();
}

/**
* @NOTE
* Some systems like Claude have to do this
* So adding it here as a standar options
*
* @param MessageInDto[] $messages
*/
protected function remapMessages(array $messages): array
{
return $messages;
}
}
57 changes: 39 additions & 18 deletions Modules/LlmDriver/app/ClaudeClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Laravel\Pennant\Feature;
use LlmLaraHub\LlmDriver\Requests\MessageInDto;
use LlmLaraHub\LlmDriver\Responses\CompletionResponse;
use LlmLaraHub\LlmDriver\Responses\EmbeddingsResponseDto;
Expand Down Expand Up @@ -39,7 +38,9 @@ public function chat(array $messages): CompletionResponse
* in betwee a user row with some copy to make it work like "And the user search results had"
* using the Laravel Collection library
*/
$messages = $this->remapMessagesForClaude($messages);
$messages = $this->remapMessages($messages);

put_fixture('orchestration_message_array_after_claude.json', $messages);

$results = $this->getClient()->post('/messages', [
'model' => $model,
Expand Down Expand Up @@ -133,7 +134,7 @@ protected function getClient()
*/
public function functionPromptChat(array $messages, array $only = []): array
{
$messages = $this->remapMessagesForClaude($messages);
$messages = $this->remapMessages($messages);
Log::info('LlmDriver::ClaudeClient::functionPromptChat', $messages);

$functions = $this->getFunctions();
Expand Down Expand Up @@ -192,10 +193,6 @@ public function getFunctions(): array
{
$functions = LlmDriverFacade::getFunctions();

if(!Feature::active('llm-driver.claude.functions')) {
return [];
}

return collect($functions)->map(function ($function) {
$function = $function->toArray();
$properties = [];
Expand Down Expand Up @@ -229,29 +226,53 @@ public function getFunctions(): array
}

/**
* @see https://docs.anthropic.com/claude/reference/messages_post
* The order of the messages has to be start is oldest
* then descending is the current
* with each one alternating between user and assistant
*
* @param MessageInDto[] $messages
*/
protected function remapMessagesForClaude(array $messages): array
protected function remapMessages(array $messages): array
{
$messages = collect($messages)->map(function ($item) {
if ($item->role === 'system') {
$item->role = 'assistant';
}

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

$messages = $messages->flatMap(function ($item, $index) use ($messages) {
if ($index > 0 && $item['role'] === 'assistant' && optional($messages->get($index + 1))['role'] === 'assistant') {
return [
$item,
['role' => 'user', 'content' => 'Continuation of search results'],
];
$lastRole = null;

$newMessagesArray = [];

foreach ($messages as $index => $message) {
$currentRole = data_get($message, 'role');

if ($currentRole === $lastRole) {
if ($currentRole === 'assistant') {
$newMessagesArray[] = [
'role' => 'user',
'content' => 'Using the surrounding context to continue this response thread',
];
} else {
$newMessagesArray[] = [
'role' => 'assistant',
'content' => 'Using the surrounding context to continue this response thread',
];
}

$newMessagesArray[] = $message;
} else {
$newMessagesArray[] = $message;
}

return [$item];
})->toArray();
$lastRole = $currentRole;

}

return $messages;
return $newMessagesArray;
}
}
5 changes: 1 addition & 4 deletions Modules/LlmDriver/app/Functions/SummarizeCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace LlmLaraHub\LlmDriver\Functions;

use App\Domains\Messages\RoleEnum;
use App\Models\Chat;
use Illuminate\Support\Facades\Log;
use LlmLaraHub\LlmDriver\HasDrivers;
use LlmLaraHub\LlmDriver\LlmDriverFacade;
Expand Down Expand Up @@ -44,10 +42,9 @@ public function handle(

$results = LlmDriverFacade::driver($model->getDriver())->chat($messagesArray);



return FunctionResponse::from([
'content' => $results->content,
'requires_followup' => true,
]);
}

Expand Down
14 changes: 13 additions & 1 deletion Modules/LlmDriver/app/Orchestrate.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Models\Chat;
use Facades\App\Domains\Messages\SearchOrSummarizeChatRepo;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use LlmLaraHub\LlmDriver\Functions\FunctionCallDto;
use LlmLaraHub\LlmDriver\Requests\MessageInDto;
use LlmLaraHub\LlmDriver\Responses\FunctionResponse;
Expand All @@ -25,10 +26,12 @@ public function handle(array $messagesArray, Chat $chat): ?string
/**
* We are looking first for functions / agents / tools
*/
Log::info('[LaraChain] Orchestration Function Check');
$functions = LlmDriverFacade::driver($chat->chatable->getDriver())
->functionPromptChat($messagesArray);

if ($this->hasFunctions($functions)) {
Log::info('[LaraChain] Orchestration Has Fucntions', $functions);
/**
* @TODO
* We will deal with multi functions shortly
Expand Down Expand Up @@ -88,10 +91,19 @@ public function handle(array $messagesArray, Chat $chat): ?string

/**
* @NOTE the function might return the results of a table
* or csv file or image info etc.
* or csv file or image info etc.o
* This prompt should consider the initial prompt and the output of the function(s)
*/
if ($this->requiresFollowup) {
Log::info('[LaraChain] Orchestration Requires Followup');

// $chat->addInput(
// message: "Use the previous assistant response to help for context to the users previous prompt",
// role: RoleEnum::User,
// show_in_thread: true);

put_fixture('orchestration_message_array_followup_pre.json', $messagesArray);

$results = LlmDriverFacade::driver($chat->chatable->getDriver())
->chat($messagesArray);

Expand Down
26 changes: 13 additions & 13 deletions Modules/LlmDriver/tests/Feature/ClaudeClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,39 +89,39 @@ public function test_chat_with_multiple_assistant_messages(): void

$results = $client->chat([
MessageInDto::from([
'content' => 'test 3',
'role' => 'assistant',
'content' => 'test',
'role' => 'user',
]),
MessageInDto::from([
'content' => 'test 2',
'content' => 'test 1',
'role' => 'assistant',
]),
MessageInDto::from([
'content' => 'test 1',
'content' => 'test 2',
'role' => 'assistant',
]),
MessageInDto::from([
'content' => 'test',
'role' => 'user',
'content' => 'test 3',
'role' => 'assistant',
]),
]);

$this->assertInstanceOf(CompletionResponse::class, $results);

Http::assertSent(function ($request) {
$message1 = $request->data()['messages'][0]['role'];
$message2 = $request->data()['messages'][1]['role'];
$message3 = $request->data()['messages'][1]['role'];
$message0 = $request->data()['messages'][0]['role'];
$message1 = $request->data()['messages'][1]['role'];
$message2 = $request->data()['messages'][2]['role'];

return $message2 === 'assistant' &&
$message1 === 'user' && $message3 === 'assistant';
return $message0 === 'assistant' &&
$message1 === 'user' && $message2 === 'assistant';
});

}

public function test_get_functions(): void
{
Feature::define('llm-driver.claude.functions', function() {
Feature::define('llm-driver.claude.functions', function () {
return true;
});
$openaiClient = new \LlmLaraHub\LlmDriver\ClaudeClient();
Expand All @@ -138,7 +138,7 @@ public function test_get_functions(): void

public function test_functions_prompt(): void
{
Feature::define('llm-driver.claude.functions', function() {
Feature::define('llm-driver.claude.functions', function () {
return true;
});
$data = get_fixture('cloud_client_tool_use_response.json');
Expand Down
2 changes: 1 addition & 1 deletion app/Domains/Messages/SearchOrSummarizeChatRepo.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function search(Chat $chat, string $input): string

$chat->addInput(
message: $content,
role: RoleEnum::User,
role: RoleEnum::Assistant,
systemPrompt: $chat->chatable->systemPrompt(),
show_in_thread: false
);
Expand Down
2 changes: 1 addition & 1 deletion tests/Feature/Http/Controllers/ChatControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function test_kick_off_chat_makes_system()
'system_prompt' => 'Foo',
'input' => 'user input',
])->assertOk();
$this->assertDatabaseCount('messages', 3);
$this->assertDatabaseCount('messages', 2);

}
}
26 changes: 26 additions & 0 deletions tests/fixtures/claude_after_messages.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[
{
"content": "if I was to break that up into slides for a presentation that last 20 minutes can you help",
"role": "user"
},
{
"content": "Here is a summary of the key points from the provided content:\n\n- The content discusses the challenges in building a specific application at Pfizer, requiring careful consideration of various nuances and specific requirements for the product.\n- It shares the author's experience of determining the right technology for a software project, whether as a lone developer or as part of a team.\n- The system was designed to work on AWS, with a strong testing foundation, and accommodate a growing team of 25 people, while enabling easy, zero-downtime deployments and migrations.\n- The system had to use technology that the team could work with, with consistent training and documentation, and a linting system to help maintain team standards.\n- The success or failure of a product is rarely due to the technology itself, but rather the alignment between the product vision and the system implementation, as well as the skills of the developers involved.\n- The document discusses the automation of minor updates and security updates, as well as the need to scale due to the use of queues.\n- The technical requirements for the project include a JavaScript-based user interface, a backend with a queue system for long-running processes, and a robust authentication system.\n- The key requirements for the system include authentication integration, feature flag management, API integration, environmental configuration management, and real-time UI updates through web sockets.\n- The importance of understanding the product owner's goals and using the appropriate technology to achieve those goals is emphasized, regardless of the scale of the business.",
"role": "assistant"
},
{
"role": "user",
"content": "Continuation of search results"
},
{
"content": "Here is a summary of the key points from the provided content:\n\n- The content discusses the challenges in building a specific application at Pfizer, requiring careful consideration of various nuances and specific requirements for the product.\n- It shares the author's experience of determining the right technology for a software project, whether as a lone developer or as part of a team.\n- The system was designed to work on AWS, with a strong testing foundation, and accommodate a growing team of 25 people, while enabling easy, zero-downtime deployments and migrations.\n- The system had to use technology that the team could work with, with consistent training and documentation, and a linting system to help maintain team standards.\n- The success or failure of a product is rarely due to the technology itself, but rather the alignment between the product vision and the system implementation, as well as the skills of the developers involved.\n- The document discusses the automation of minor updates and security updates, as well as the need to scale due to the use of queues.\n- The technical requirements for the project include a JavaScript-based user interface, a backend with a queue system for long-running processes, and a robust authentication system.\n- The key requirements for the system include authentication integration, feature flag management, API integration, environmental configuration management, and real-time UI updates through web sockets.\n- The importance of understanding the product owner's goals and using the appropriate technology to achieve those goals is emphasized, regardless of the scale of the business.",
"role": "assistant"
},
{
"content": "can you make slide numbers and ideas from this",
"role": "user"
},
{
"content": "This is data from the search results when entering the users prompt which is ### START PROMPT ### can you make slide numbers and ideas from this ### END PROMPT ### please use this with the following context and only this and return as markdown so I can render it: brain dump context talk, middl I list bullet point lead into. good sens context I turn slide surfac Technolog parts. I think I like interact Q I possibl audienc like that? One, I go start concept technolog doe alway matters\/ I want focus technolog abl achiev product owner goal understand goal key. build saa person compani 100 just know goal use right tech goal. 13) use technolog team work skill did current team 14) Consist Train document (team standards, ci\/cd etc) ideal stack amaz document community. 15) Lint help team standard 16) Autom Minor updat 17) Autom Secur (kinda happen Minor updates) 18) scale (queue big this) I ask build specif applic I contract Pfizer requir lot nuances. product I build thing present. (final list end)",
"role": "assistant"
}
]
14 changes: 14 additions & 0 deletions tests/fixtures/claude_before_messages.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"content": "if I was to break that up into slides for a presentation that last 20 minutes can you help",
"role": "user"
},
{
"content": "See content from the surrounding user messages to understand the context of the request.",
"role": "assistant"
},
{
"content": "Here is a summary of the key points from the provided content:\n\n- The content discusses the challenges in building a specific application at Pfizer, requiring careful consideration of various nuances and specific requirements for the product.\n- It shares the author's experience of determining the right technology for a software project, whether as a lone developer or as part of a team.\n- The system was designed to work on AWS, with a strong testing foundation, and accommodate a growing team of 25 people, while enabling easy, zero-downtime deployments and migrations.\n- The system had to use technology that the team could work with, with consistent training and documentation, and a linting system to help maintain team standards.\n- The success or failure of a product is rarely due to the technology itself, but rather the alignment between the product vision and the system implementation, as well as the skills of the developers involved.\n- The document discusses the automation of minor updates and security updates, as well as the need to scale due to the use of queues.\n- The technical requirements for the project include a JavaScript-based user interface, a backend with a queue system for long-running processes, and a robust authentication system.\n- The key requirements for the system include authentication integration, feature flag management, API integration, environmental configuration management, and real-time UI updates through web sockets.\n- The importance of understanding the product owner's goals and using the appropriate technology to achieve those goals is emphasized, regardless of the scale of the business.",
"role": "user"
}
]
10 changes: 10 additions & 0 deletions tests/fixtures/orchestration_message_array_after_claude.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"content": "Can you help me make a list of slide ideas from this content",
"role": "user"
},
{
"content": "This is data from the search results when entering the users prompt which is ### START PROMPT ### Can you help me make a list of slide ideas from this content ### END PROMPT ### please use this with the following context and only this and return as markdown so I can render it: brain dump context talk, middl I list bullet point lead into. good sens context I turn slide surfac Technolog parts. I think I like interact Q I possibl audienc like that? I ask build specif applic I contract Pfizer requir lot nuances. product I build thing present. (final list end) One, I go start concept technolog doe alway matters\/ I want focus technolog abl achiev product owner goal understand goal key. build saa person compani 100 just know goal use right tech goal. 13) use technolog team work skill did current team 14) Consist Train document (team standards, ci\/cd etc) ideal stack amaz document community. 15) Lint help team standard lead right tech I go make right tech lone dev team just tri figur right tech let share I went figur tih Pfizer 12 year ago I think work today.",
"role": "assistant"
}
]

0 comments on commit 363a63a

Please sign in to comment.