Skip to content
This repository was archived by the owner on Jan 5, 2025. It is now read-only.

Commit da91419

Browse files
authored
Merge pull request #13 from openchatai/feat/github-data-source
(wip) Feat/GitHub data source
2 parents 2df9eea + 5585346 commit da91419

30 files changed

+1158
-156
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ https://github.com/openchatai/OpenChat/assets/32633162/c1e0cea1-6627-47c3-becc-c
3535
- Customize your chatbots by providing PDF files, websites, and soon, integrations with platforms like Notion, Confluence, and Office 365.
3636
- Each chatbot has unlimited memory capacity, enabling seamless interaction with large files such as a 400-page PDF.
3737
- Embed chatbots as widgets on your website or internal company tools.
38+
- Use your entire codebase as a data source for your chatbots (pair programming mode).
3839
- And much more!
3940

4041
## 🛣️ Roadmap:
@@ -46,6 +47,7 @@ https://github.com/openchatai/OpenChat/assets/32633162/c1e0cea1-6627-47c3-becc-c
4647
- [x] Accept websites as a data source
4748
- [x] Accept PDF files as a data source
4849
- [x] Support multiple data sources per chatbot
50+
- [x] Support ingesting an entire codebase using GitHub API and use it as a data source with pair programming mode
4951
- [ ] Support Slack integration (allow users to connect chatbots with their Slack workspaces)
5052
- [ ] Support Intercom integration (enable users to sync chat conversations with Intercom)
5153
- [ ] Support offline open-source models (e.g., Alpaca, LLM drivers)

backend-server/app/Http/Controllers/ChatbotController.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@
33
namespace App\Http\Controllers;
44

55
use App\Http\Events\ChatbotWasCreated;
6+
use App\Http\Events\CodebaseDataSourceWasAdded;
67
use App\Http\Events\PdfDataSourceWasAdded;
78
use App\Http\Requests\CreateChatbotRequest;
9+
use App\Http\Requests\CreateChatbotViaCodebaseRequest;
810
use App\Http\Requests\CreateChatbotViaPdfFlowRequest;
911
use App\Http\Requests\SendChatMessageRequest;
1012
use App\Http\Requests\UpdateCharacterSettingsRequest;
1113
use App\Http\Responses\ChatbotResponse;
1214
use App\Http\Services\HandlePdfDataSource;
1315
use App\Models\Chatbot;
16+
use App\Models\CodebaseDataSource;
1417
use Illuminate\Http\JsonResponse;
1518
use Illuminate\Http\RedirectResponse;
1619
use Illuminate\Support\Facades\Http;
@@ -133,17 +136,19 @@ public function sendMessage(SendChatMessageRequest $request, $token): JsonRespon
133136
// Get the question and history from the request
134137
$question = $request->getMessage();
135138
$history = $request->getHistory();
139+
$mode = $request->getMode();
136140

137141
// Remove null and empty values and empty arrays or objects from the history
138142
$history = array_filter($history, function ($value) {
139143
return !is_null($value) && $value !== '' && $value !== [] && $value !== (object) [];
140144
});
141145

142146
// Call the API to send the message to the chatbot with a timeout of 5 seconds
143-
$response = Http::connectTimeout(60)->post("http://llm-server:3000/api/chat", [
147+
$response = Http::timeout(200)->post("http://llm-server:3000/api/chat", [
144148
'question' => $question,
145149
'history' => $history,
146150
'namespace' => $bot->getId()->toString(),
151+
'mode' => $mode,
147152
]);
148153

149154
if ($response->failed()) {
@@ -178,4 +183,28 @@ public function getChatView($token)
178183
'bot' => $bot,
179184
]);
180185
}
186+
187+
public function createViaCodebaseFlow(CreateChatbotViaCodebaseRequest $request): RedirectResponse
188+
{
189+
$chatbot = new Chatbot();
190+
$chatbot->setId(Uuid::uuid4());
191+
$chatbot->setName($request->getName());
192+
$chatbot->setToken(Str::random(20));
193+
$chatbot->setPromptMessage($request->getPromptMessage());
194+
$chatbot->save();
195+
196+
$datasource = new CodebaseDataSource();
197+
$datasource->setId(Uuid::uuid4());
198+
$datasource->setChatbotId($chatbot->getId());
199+
$datasource->setRepository($request->getRepoUrl());
200+
$datasource->save();
201+
202+
203+
event(new CodebaseDataSourceWasAdded(
204+
$chatbot->getId(),
205+
$datasource->getId())
206+
);
207+
208+
return redirect()->route('onboarding.config', ['id' => $chatbot->getId()->toString()]);
209+
}
181210
}

backend-server/app/Http/Controllers/ChatbotSettingController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,13 @@ public function dataSettings(Request $request, $id)
6565
// Get website data sources and PDF data sources for the chatbot
6666
$websiteDataSources = $bot->getWebsiteDataSources()->get();
6767
$pdfDataSources = $bot->getPdfFilesDataSources()->get();
68+
$codebaseDataSources = $bot->getCodebaseDataSources()->get();
6869

6970
return view('settings-data', [
7071
'bot' => $bot,
7172
'websiteDataSources' => $websiteDataSources,
7273
'pdfDataSources' => $pdfDataSources,
74+
'codebaseDataSources' => $codebaseDataSources,
7375
]);
7476
}
7577

backend-server/app/Http/Controllers/OnboardingController.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,9 @@ public function done()
3535
{
3636
return view('onboarding.step-4');
3737
}
38+
39+
public function dataSourcesCodebase()
40+
{
41+
return view('onboarding.step-2-codebase');
42+
}
3843
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
namespace App\Http\Enums;
4+
5+
class IngestStatusType
6+
{
7+
public const SUCCESS= 'success';
8+
public const FAILED = 'failed';
9+
10+
11+
public function __construct(private readonly string $status)
12+
{
13+
if (!self::isValid($status)) {
14+
throw new \InvalidArgumentException("Invalid status: {$status}");
15+
}
16+
}
17+
18+
public static function getTypes(): array
19+
{
20+
return [
21+
self::SUCCESS,
22+
self::FAILED,
23+
];
24+
}
25+
26+
public static function getLabels(): array
27+
{
28+
return [
29+
self::SUCCESS => 'Success',
30+
self::FAILED => 'Failed',
31+
];
32+
}
33+
34+
public function getLabel(): string
35+
{
36+
return self::getLabels()[$this->getStatus()];
37+
}
38+
39+
public static function getValues(): array
40+
{
41+
return array_keys(self::getLabels());
42+
}
43+
44+
public static function isValid(string $type): bool
45+
{
46+
return in_array($type, self::getValues());
47+
}
48+
49+
public function isSuccessful(): bool
50+
{
51+
return $this->getStatus() === self::SUCCESS;
52+
}
53+
54+
public function isFailed(): bool
55+
{
56+
return $this->getStatus() === self::FAILED;
57+
}
58+
59+
public function getStatus(): string
60+
{
61+
return $this->status;
62+
}
63+
64+
public function __toString(): string
65+
{
66+
return $this->getStatus();
67+
}
68+
69+
public function equals(IngestStatusType $type): bool
70+
{
71+
return $this->getStatus() === $type->getStatus();
72+
}
73+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace App\Http\Events;
4+
5+
use Illuminate\Broadcasting\InteractsWithSockets;
6+
use Illuminate\Foundation\Events\Dispatchable;
7+
use Illuminate\Queue\SerializesModels;
8+
use Ramsey\Uuid\UuidInterface;
9+
10+
class CodebaseDataSourceWasAdded
11+
{
12+
use Dispatchable, InteractsWithSockets, SerializesModels;
13+
14+
public function __construct(
15+
private UuidInterface $chatbotId,
16+
private UuidInterface $codebaseDataSourceId,
17+
) {
18+
}
19+
20+
public function getChatbotId(): UuidInterface
21+
{
22+
return $this->chatbotId;
23+
}
24+
25+
public function getCodebaseDataSourceId(): UuidInterface
26+
{
27+
return $this->codebaseDataSourceId;
28+
}
29+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
namespace App\Http\Listeners;
4+
5+
use App\Http\Enums\IngestStatusType;
6+
use App\Http\Events\CodebaseDataSourceWasAdded;
7+
use App\Models\CodebaseDataSource;
8+
use Exception;
9+
use GuzzleHttp\Client;
10+
use GuzzleHttp\Exception\GuzzleException;
11+
use Illuminate\Contracts\Queue\ShouldQueue;
12+
13+
class IngestCodebaseDataSource implements ShouldQueue
14+
{
15+
16+
/**
17+
* @throws GuzzleException
18+
* @throws Exception
19+
*/
20+
public function handle($event)
21+
{
22+
if (!$event instanceof CodebaseDataSourceWasAdded) {
23+
return;
24+
}
25+
26+
$botId = $event->getChatbotId();
27+
$codebaseDataSourceId = $event->getCodebaseDataSourceId();
28+
29+
30+
/** @var CodebaseDataSource $datasource */
31+
$datasource = CodebaseDataSource::find($codebaseDataSourceId);
32+
33+
34+
$repo = $datasource->getRepository();
35+
36+
$requestBody = [
37+
'type' => 'codebase',
38+
'repo' => $repo,
39+
'namespace' => $botId,
40+
];
41+
42+
// Call to ingest service endpoint
43+
$client = new Client();
44+
$response = $client->request('POST', 'http://llm-server:3000/api/ingest', [
45+
'json' => $requestBody,
46+
]);
47+
48+
$datasource->setIngestedAt(now());
49+
50+
if ($response->getStatusCode() !== 200) {
51+
$datasource->setIngestionStatus(IngestStatusType::FAILED);
52+
} else {
53+
$datasource->setIngestionStatus(IngestStatusType::SUCCESS);
54+
}
55+
56+
$datasource->save();
57+
}
58+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace App\Http\Requests;
4+
5+
6+
use App\Http\Rules\GithubRepoUrlRule;
7+
use Illuminate\Foundation\Http\FormRequest;
8+
9+
class CreateChatbotViaCodebaseRequest extends FormRequest
10+
{
11+
public function rules(): array
12+
{
13+
return [
14+
'repo' => ['required', new GithubRepoUrlRule],
15+
];
16+
}
17+
18+
public function getRepoUrl(): string
19+
{
20+
return $this->get('repo');
21+
}
22+
23+
public function getRepoAccessToken(): ?string
24+
{
25+
return $this->get('token');
26+
}
27+
28+
public function getName(): string
29+
{
30+
return $this->get('name', 'My first chatbot');
31+
}
32+
33+
public function getPromptMessage(): string
34+
{
35+
return $this->get('prompt_message', "");
36+
}
37+
}

backend-server/app/Http/Requests/SendChatMessageRequest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public function rules(): array
1212
{
1313
return [
1414
'message' => 'required|string',
15+
'mode' => 'sometimes|string|in:assistant,pair_programmer',
1516
];
1617
}
1718

@@ -24,4 +25,9 @@ public function getHistory(): array
2425
{
2526
return $this->get('history');
2627
}
28+
29+
public function getMode(): string
30+
{
31+
return $this->get('mode');
32+
}
2733
}

backend-server/app/Http/Responses/ChatbotResponse.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ public function getBotReply(): string
1515

1616
public function getSourceDocuments(): array
1717
{
18-
return $this->response['sourceDocuments'];
18+
return $this->response['sourceDocuments'] ?? [];
1919
}
2020
}

0 commit comments

Comments
 (0)