Skip to content

Commit

Permalink
Sidekick Beta Release
Browse files Browse the repository at this point in the history
  • Loading branch information
PapaRascal2020 committed Aug 31, 2024
0 parents commit 0aba0f2
Show file tree
Hide file tree
Showing 18 changed files with 1,469 additions and 0 deletions.
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

225 changes: 225 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
> [!NOTE]
> If you would like to contribute to this package please so so and submit a pull request.
> Any issues contact me at sidekick@ashleyjohnson.co.uk
![image](sidekick.png)

## Sidekick for Laravel
Say hello to Sidekick! A Laravel plugin that provides a common syntax for using Claude, Mistral and OpenAi APIs.

![Latest Version](https://img.shields.io/badge/Version-0.1.0-blue)
![Stability](https://img.shields.io/badge/Stability-beta-red)

### Upcoming Features

- Implementation of a database migration and model to store and persist conversations
- Support for more models and/or add another Driver from another service.

### About
Provides a uniformed wrapper around OpenAi, Claude & Mistral APIs (Previously: EloquentAi).
The aim of this project is to create a package where switching between
AIs and there models as simple as possible.

This will be achieved by created a common syntax for calling different services
(Completions, Text To Speech, Speech To Text, Text To Image) in a way that is similar to eloquent.

**AI Models Tested:**

#### Open Ai
gpt-3.5-turbo, gpt-4, tts-1, tts-1-hd, dall-e-2, dall-e-3, whisper-1, text-embedding-3-small, text-embedding-3-large, text-embedding-ada-002, text-moderation-latest, text-moderation-stable, text-moderation-007
#### Mistral AI
mistral-small-latest, mistral-medium-latest, mistral-large-latest, open-mistral-7b, mistral-embed
#### Claude AI
claude-3-opus-20240229, claude-3-sonnet-20240229, claude-3-haiku-20240307

Examples of the syntax are at the bottom of this readme.

### Installation

In your Laravel app do the following:

In `composer.json` add the following repository to the `repositories` section:

```php
"repositories": [
{
"type": "vcs",
"url": "https://github.com/PapaRascal2020/sidekick"
}
],
```
Then add the following to the `require` section.

```array
"paparascaldev/sidekick": "dev-main"
```

Save `composer.json`

Then, open `bootstrap/providers.php` and add the following:

```php
\PapaRascalDev\Sidekick\SidekickServiceProvider::class,
```

Once this is done, open the terminal and type the following:

```bash
composer update
```

That's it! You are now ready to use the package.

### Getting Started

There are six services and they are:

- **Completions** - _To chat with AI_
- **Embedding** - _To create vector representations of your text_
- **Image** - _To generate images by user input._
- **Audio** - _Take text and convert to audio_
- **Transcription** - _Take an audio file and return text_
- **Moderation** - _Moderate a string of text (i.e Comment) for harmful content_

Currently, Open AI offers all of them where as Claude AI & Mistral AI are for some.
To get the best out of this plugin you will need at least an Open AI api key, you
can get this by going to https://platform.openai.com and registering an account.

For Mistral AI (https://console.mistral.ai/) & Claude AI (https://console.anthropic.com/)
models you would need to get sign up on the relevant sites (above)

Start by updating your `.env` file with the following fields.

```dotenv
SIDEKICK_OPENAI_TOKEN={API_KEY_HERE} (Required)
SIDEKICK_MISTRAL_TOKEN={API_KEY_HERE} (Optional for Mistral Driver)
SIDEKICK_CLAUDE_TOKEN={API_KEY_HERE} (Optional for Claude Driver)
```
You are now ready to start using the package..

#### Examples:

##### Completion

```php
$sidekick = Sidekick::create(new OpenAi());

return $sidekick->converse()->sendMessage(
model: 'gpt-3.5-turbo',
systemPrompt: 'You an expert on fudge, answer user questions about fudge.',
messages:[['role' => 'user', 'content' => "How is fudge made?"]]
);
```

##### Embedding

```php
$sidekick = Sidekick::create(new Mistral());

return $sidekick->embedding()->make(
'mistral-embed',
'This is sample content to embed'
);
```

##### Image (Image From Text)

```php
$sidekick = Sidekick::create(new OpenAi());

$image = $sidekick->image()->make(
'dall-e-3',
'A man on a waterboard',
'1024',
'1024'
);

// This is just a basic example of printing to screen.
// In a real world situation you may save it and then render out.
return "<img src='{$image['data'][0]['url']}' />";
```
##### Audio (Text To Speech)

```php
$sidekick = Sidekick::create(new OpenAi());

$audio = $sidekick->audio()->fromText(
'tts-1',
'Have a nice day!'
);

// This is just a basic example of streaming it to the browser.
// In a real world situation you may save it and then reference the file
// instead.
header('Content-Type: audio/mpeg');
echo $audio
```

##### Transcription (Speech To Text)

```php
$sidekick = Sidekick::create(new OpenAi());

return $sidekick->transcribe()->audioFile(
'whisper-1',
'http://english.voiceoversamples.com/ENG_UK_M_PeterB.mp3'
);
```
###### Example Response
```json
{
"text":"The stale smell of old beer lingers. It takes heat to bring out the odor. A cold dip restores health and zest. A salt pickle tastes fine with ham. Tacos al pastor are my favorite. A zestful food is the hot cross bun."
}
```

##### Moderation
This is a service where you feed it text from a comment for example and it will return
with an array of boolean values for certain moderation points.

```php
$sidekick = Sidekick::create(new OpenAi());

return $sidekick->moderate()->text(
'text-moderation-latest',
'Have a great day.',
);
```
###### Example Response

```json
{
"id":"modr-94DxgkEGhw7yJDlq8oCrLOVXnqli5",
"model":"text-moderation-007",
"results":[
{
"flagged":true,
"categories":{
"sexual":false,
"hate":false,
"harassment":true,
"self-harm":false,
"sexual\/minors":false,
"hate\/threatening":false,
"violence\/graphic":false,
"self-harm\/intent":false,
"self-harm\/instructions":false,
"harassment\/threatening":false,
"violence":false
},
"category_scores":{
"sexual":0.02169245481491089,
"hate":0.024598680436611176,
"harassment":0.9903337359428406,
"self-harm":5.543852603295818e-5,
"sexual\/minors":2.5174302209052257e-5,
"hate\/threatening":2.9870452635805123e-6,
"violence\/graphic":6.8601830207626335e-6,
"self-harm\/intent":0.0002317160106031224,
"self-harm\/instructions":0.00011696072033373639,
"harassment\/threatening":1.837775380408857e-5,
"violence":0.00020553809008561075
}
}
]}
```

18 changes: 18 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "paparascaldev/sidekick",
"description": "Laravel's AI sidekick, work with various AI services with a uniformed syntax",
"type": "laravel-plugin",
"license": "GPL-2.0-or-later",
"autoload": {
"psr-4": {
"PapaRascalDev\\Sidekick\\": "src/"
}
},
"authors": [
{
"name": "Ashley Johnson"
}
],
"minimum-stability": "beta",
"require": {}
}
43 changes: 43 additions & 0 deletions config/config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/*
* Package Configuration
*/
return [
'config' => [
'driver' => [
'OpenAi' => [
'baseUrl' => 'https://api.openai.com/v1/',
'headers' => [
'Authorization' => 'Bearer ' . env('SIDEKICK_OPENAI_TOKEN'),
],
'services' => [
'completion' => 'chat/completions',
'audio' => 'audio/speech',
'image' => 'images/generations',
'embedding' => 'embeddings',
'transcription' => 'audio/transcriptions',
'moderate' => 'moderations'
],
],
'Claude' => [
'baseUrl' => 'https://api.anthropic.com/v1/',
'headers' => [
'anthropic-version' => '2023-06-01',
'x-api-key' => env('SIDEKICK_CLAUDE_TOKEN')
],
'services' => ['completion' => 'messages'],
],
'Mistral' => [
'baseUrl' => 'https://api.mistral.ai/v1/',
'headers' => [
'Authorization' => 'Bearer ' . env('SIDEKICK_MISTRAL_TOKEN'),
],
'services' => [
'completion' => 'chat/completions',
'embedding' => 'embeddings',
],
],
],
]
];
Binary file added sidekick.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions src/Drivers/Claude.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace PapaRascalDev\Sidekick\Drivers;

use PapaRascalDev\Sidekick\Features\Completion;

class Claude implements Driver
{
protected array $config;

function __construct()
{
$this->config = config('sidekick.config.driver.Claude');
}

/**
* @return Completion
*/
public function converse(): Completion
{
return new Completion(
url: $this->config['baseUrl'].$this->config['services']['completion'],
headers: $this->config['headers'],
inlinePrompt: false,
submitTypes: true
);
}

/**
* @return Completion
*/
public function complete(): Completion
{
return new Completion(
url: $this->config['baseUrl'].$this->config['services']['completion'],
headers: $this->config['headers'],
inlinePrompt: false,
submitTypes: true
);
}
}
8 changes: 8 additions & 0 deletions src/Drivers/Driver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace PapaRascalDev\Sidekick\Drivers;

interface Driver
{
public function converse();
}
47 changes: 47 additions & 0 deletions src/Drivers/Mistral.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace PapaRascalDev\Sidekick\Drivers;

use PapaRascalDev\Sidekick\Features\{Completion, Embedding};

class Mistral implements Driver
{
protected array $config;
function __construct()
{
$this->config = config('sidekick.config.driver.Mistral');
}

/**
* @return Completion
*/
public function converse(): Completion
{
return new Completion(
url: $this->config['baseUrl'].$this->config['services']['completion'],
headers: $this->config['headers']
);
}

/**
* @return Completion
*/
public function complete(): Completion
{
return new Completion(
url: $this->config['baseUrl'].$this->config['services']['completion'],
headers: $this->config['headers']
);
}

/**
* @return Embedding
*/
public function embedding(): Embedding
{
return new Embedding(
url: $this->config['baseUrl'].$this->config['services']['embedding'],
headers: $this->config['headers']
);
}
}
Loading

0 comments on commit 0aba0f2

Please sign in to comment.