diff --git a/app/Http/Controllers/OutboundController.php b/app/Http/Controllers/OutboundController.php index 52b965f..bfa4496 100644 --- a/app/Http/Controllers/OutboundController.php +++ b/app/Http/Controllers/OutboundController.php @@ -4,26 +4,26 @@ use App\Models\Outbound; use App\Models\Project; -use Illuminate\Http\Request; +use App\ResponseType\ResponseDto; class OutboundController extends Controller { public function __invoke(Project $project, Outbound $outbound) { /** @TODO find route binding for this */ - if($outbound->project_id !== $project->id) { + if ($outbound->project_id !== $project->id) { abort(404); } + $validated = request()->validate([ + 'question' => ['required', 'max:5000'], + ]); - /** - * @TODO they all have to be the same response type - * either a DTO or string - * maybe I need the status too? - * some might put a job on a queue - * some might need to be waited for - * some might use pusher so a queue etc - */ - //$response = outbound run - return response("", 200); + $user = auth()->user(); + $request = $validated['question']; + + /** @var ResponseDto $response */ + $response = $outbound->run($user, $request); + + return response($response->response, $response->status); } } diff --git a/app/Models/Outbound.php b/app/Models/Outbound.php index 4c0d770..6b7eb21 100644 --- a/app/Models/Outbound.php +++ b/app/Models/Outbound.php @@ -6,37 +6,56 @@ use App\Outbound\OutboundEnum; use App\ResponseType\BaseResponseType; use App\ResponseType\ResponseDto; +use App\ResponseType\ResponseTypeEnum; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +/** + * @property ResponseTypeEnum $type + * @property int $project_id + * @property Project $project; + * @property array $prompt_token; + * @property Collection $response_types; + * + * @method Project project() + */ class Outbound extends Model { use HasFactory; + protected ResponseDto $currentResponseDto; + protected $guarded = []; protected $casts = [ 'type' => OutboundEnum::class, - 'active' => "bool" + 'active' => 'bool', ]; - public function project() { + public function project() + { return $this->belongsTo(Project::class); } + public function response_types() + { + return $this->hasMany(ResponseType::class)->orderBy('order'); + } + /** * @throws ResponseTypeMissingException */ public function run(User $user, string $request): ResponseDto { - try { + $message = new Message([ + 'role' => 'user', + 'content' => $request, + 'user_id' => $user->id, + 'project_id' => $this->project_id, + ]); - $message = new Message([ - 'role' => 'user', - 'content' => $request, - 'user_id' => $user->id, - 'project_id' => $this->project_id, - ]); + try { $dto = ResponseDto::from([ 'message' => $message, @@ -44,7 +63,7 @@ public function run(User $user, string $request): ResponseDto $this->currentResponseDto = $dto; - foreach ($this->project->response_types as $response_type_model) { + foreach ($this->response_types as $response_type_model) { $responseType = $response_type_model->type->label(); $responseTypeClass = app("App\ResponseType\Types\\".$responseType, [ 'project' => $this->project, @@ -57,7 +76,12 @@ public function run(User $user, string $request): ResponseDto return $this->currentResponseDto; } catch (\Exception $e) { logger($e); - throw new ResponseTypeMissingException(); + + return ResponseDto::from([ + 'status' => 500, + 'message' => $message, + 'response' => $e->getMessage(), + ]); } } } diff --git a/app/Models/Project.php b/app/Models/Project.php index 776447c..5660b17 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -42,11 +42,6 @@ public function sources() return $this->hasMany(Source::class)->orderBy('order'); } - public function response_types() - { - return $this->hasMany(ResponseType::class)->orderBy('order'); - } - public function outbounds() { return $this->hasMany(Outbound::class); diff --git a/app/Models/ResponseType.php b/app/Models/ResponseType.php index e786c71..cb3e3db 100644 --- a/app/Models/ResponseType.php +++ b/app/Models/ResponseType.php @@ -2,8 +2,6 @@ namespace App\Models; -use App\Exceptions\ResponseTypeMissingException; -use App\ResponseType\BaseResponseType; use App\ResponseType\ResponseDto; use App\ResponseType\ResponseTypeEnum; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -11,11 +9,11 @@ /** * @property ResponseTypeEnum $type - * @property int $project_id - * @property Project $project; + * @property int $outbound_id + * @property Outbound $outbound; * @property array $prompt_token; * - * @method Project project() + * @method Outbound outbound() */ class ResponseType extends Model { @@ -30,10 +28,8 @@ class ResponseType extends Model 'type' => ResponseTypeEnum::class, ]; - public function project() + public function outbound() { - return $this->belongsTo(Project::class); + return $this->belongsTo(Outbound::class); } - - } diff --git a/app/ResponseType/ResponseDto.php b/app/ResponseType/ResponseDto.php index e2d443d..d28d188 100644 --- a/app/ResponseType/ResponseDto.php +++ b/app/ResponseType/ResponseDto.php @@ -9,7 +9,8 @@ class ResponseDto extends Data { public function __construct( public Message $message, - public mixed $response + public mixed $response, + public int $status = 200 ) { } } diff --git a/database/factories/ResponseTypeFactory.php b/database/factories/ResponseTypeFactory.php index 3cb3eb3..7a113db 100644 --- a/database/factories/ResponseTypeFactory.php +++ b/database/factories/ResponseTypeFactory.php @@ -2,7 +2,7 @@ namespace Database\Factories; -use App\Models\Project; +use App\Models\Outbound; use App\ResponseType\ResponseTypeEnum; use Illuminate\Database\Eloquent\Factories\Factory; @@ -22,7 +22,7 @@ public function definition(): array 'order' => fake()->randomDigitNotZero(), 'prompt_token' => [], 'type' => ResponseTypeEnum::ChatUi, - 'project_id' => Project::factory(), + 'outbound_id' => Outbound::factory(), ]; } diff --git a/database/migrations/2023_05_09_220336_create_outbounds_table.php b/database/migrations/2023_05_09_220336_create_outbounds_table.php index ce389f5..0009780 100644 --- a/database/migrations/2023_05_09_220336_create_outbounds_table.php +++ b/database/migrations/2023_05_09_220336_create_outbounds_table.php @@ -15,8 +15,8 @@ public function up(): void { Schema::create('outbounds', function (Blueprint $table) { $table->id(); - $table->string("type")->default(OutboundEnum::ChatUi->value); - $table->boolean("active")->default(1); + $table->string('type')->default(OutboundEnum::ChatUi->value); + $table->boolean('active')->default(1); $table->foreignIdFor(Project::class); $table->timestamps(); }); diff --git a/database/migrations/2023_05_10_001152_move_relationship_off_response_types.php b/database/migrations/2023_05_10_001152_move_relationship_off_response_types.php new file mode 100644 index 0000000..722dfaf --- /dev/null +++ b/database/migrations/2023_05_10_001152_move_relationship_off_response_types.php @@ -0,0 +1,30 @@ +dropColumn('project_id'); + $table->foreignIdFor(Outbound::class); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('response_types', function (Blueprint $table) { + // + }); + } +}; diff --git a/phpunit.xml b/phpunit.xml index 3be5fdd..427e805 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,32 +1,29 @@ - - - - ./tests/Unit - - - ./tests/Feature - - - - - ./app - - - - - - - - - - - - - - + + + + ./tests/Unit + + + ./tests/Feature + + + + + + + + + + + + + + + + + + ./app + + diff --git a/phpunit.xml.bak b/phpunit.xml.bak new file mode 100644 index 0000000..3be5fdd --- /dev/null +++ b/phpunit.xml.bak @@ -0,0 +1,32 @@ + + + + + ./tests/Unit + + + ./tests/Feature + + + + + ./app + + + + + + + + + + + + + + + diff --git a/tests/Feature/ChatUiTest.php b/tests/Feature/ChatUiTest.php index 674b73b..1354c24 100644 --- a/tests/Feature/ChatUiTest.php +++ b/tests/Feature/ChatUiTest.php @@ -3,6 +3,7 @@ namespace Tests\Feature; use App\Models\Message; +use App\Models\Outbound; use App\Models\Project; use App\Models\ResponseType; use App\ResponseType\ResponseDto; @@ -44,7 +45,7 @@ public function test_can_make_messages() ]); $this->assertDatabaseCount('messages', 1); - $chatUi = new ChatUi($rt->project, $responseDto); + $chatUi = new ChatUi($rt->outbound->project, $responseDto); $chatUi->handle($rt); $this->assertDatabaseCount('messages', 3); $this->assertNotNull(Message::whereRole('system')->first()); @@ -59,6 +60,9 @@ public function test_makes_assistant_message() ->andReturn('Foo bar'); $project = Project::factory()->create(); + $outbound = Outbound::factory()->create([ + 'project_id' => $project->id, + ]); $message = Message::factory()->create([ 'project_id' => $project->id, ]); @@ -76,7 +80,7 @@ public function test_makes_assistant_message() $rt = ResponseType::factory() ->chatUi() ->create([ - 'project_id' => $project->id, + 'outbound_id' => $outbound->id, ]); $this->assertDatabaseCount('messages', 2); diff --git a/tests/Feature/Http/Controllers/OutboundControllerTest.php b/tests/Feature/Http/Controllers/OutboundControllerTest.php index 7874811..d22ddde 100644 --- a/tests/Feature/Http/Controllers/OutboundControllerTest.php +++ b/tests/Feature/Http/Controllers/OutboundControllerTest.php @@ -1,5 +1,5 @@ todo(); diff --git a/tests/Feature/Models/OutboundTest.php b/tests/Feature/Models/OutboundTest.php index 16ec4fa..9ee6961 100644 --- a/tests/Feature/Models/OutboundTest.php +++ b/tests/Feature/Models/OutboundTest.php @@ -1,6 +1,5 @@ create(); expect($model->type)->toBeInstanceOf(OutboundEnum::class); }); -it("has relations to project", function () { +it('has relations to project', function () { - $model = Outbound::factory()->create(); + $model = Outbound::factory()->has(ResponseType::factory(), 'response_types')->create(); expect($model->project->id)->not->toBeNull(); expect($model->project->outbounds->first()->id)->not->toBeNull(); + expect($model->response_types->first()->id)->not->toBeNull(); }); -it("should ru the related response types", function () { +it('should ru the related response types', function () { $user = User::factory()->create(); $request = 'Foo bar'; @@ -34,11 +34,12 @@ $project = Project::factory()->create(); $outbound = Outbound::factory()->create([ - 'project_id' => $project->id + 'project_id' => $project->id, ]); /** @var ResponseType $responseType */ ResponseType::factory()->create([ + 'outbound_id' => $outbound->id, 'type' => ResponseTypeEnum::EmbedQuestion, ]); @@ -58,7 +59,6 @@ }); - //public function test_runs_embed_then_search() //{ // $user = User::factory()->create(); diff --git a/tests/Feature/Models/ResponseTypeTest.php b/tests/Feature/Models/ResponseTypeTest.php index 2769c15..ebf9f38 100644 --- a/tests/Feature/Models/ResponseTypeTest.php +++ b/tests/Feature/Models/ResponseTypeTest.php @@ -2,14 +2,8 @@ namespace Tests\Feature\Models; -use App\LLMModels\OpenAi\EmbeddingsResponseDto; -use App\Models\Document; -use App\Models\Project; use App\Models\ResponseType; -use App\Models\User; -use App\ResponseType\ResponseDto; use App\ResponseType\ResponseTypeEnum; -use Facades\App\LLMModels\OpenAi\ClientWrapper; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; @@ -22,8 +16,7 @@ public function test_factory_rt() $model = ResponseType::factory()->create(); $this->assertEquals(ResponseTypeEnum::ChatUi, $model->type); - $this->assertNotNull($model->project->id); - $this->assertNotNull($model->project->response_types->first()->id); + $this->assertNotNull($model->outbound->id); + $this->assertNotNull($model->outbound->response_types->first()->id); } - }