Intégration du GPT d’Openai avec Angular: un guide étape par étape

Apprenez à intégrer le modèle OpenAI GPT dans une application angulaire et renvoyez une réponse de streaming du modèle Openai GPT-3.5-Turbo pour une invite donnée.
Dans cet article, nous allons parcourir le processus étape par étape d’intégration du modèle Openai GPT dans une application angulaire. Pour commencer, créez un nouveau projet angulaire et suivez chaque étape au fur et à mesure. Veuillez noter que vous aurez besoin d’une clé API OpenAI valide pour continuer.
Ajout de fichiers environnementaux
Par défaut, les versions plus récentes des projets angulaires ne sont pas livrées avec des fichiers environnementaux. Alors, créons un en exécutant la commande CLI suivante:
ng generate environments
Nous créons des fichiers environnementaux pour stocker la clé API OpenAI et l’URL de base. Dans le fichier, ajoutez des propriétés ci-dessous.
export const environment = {
production: false,
openaiApiKey: 'YOUR_DEV_API_KEY',
openaiApiUrl: 'https://api.openai.com/v1',
};
Vous pouvez trouver la clé API OpenAI ici: https://platform.openai.com/settings/organization/api-keys
Ajout de service
Nous nous connecterons au modèle OpenAI dans un service angulaire. Alors, créons un en exécutant la commande CLI suivante:
ng g s open-ai
Dans le service, nous commençons par injecter le HTTPClient pour gérer les demandes de l’API, et nous récupérons l’URL de l’API OpenAI et la clé à partir du fichier de configuration de l’environnement.
private http = inject(HttpClient);
private apiKey = environment.openaiApiKey;
private apiUrl = environment.openaiApiUrl;
Assurez-vous que le fichier app.config.ts comprend le provideHttpClient()
fonction dans le tableau des fournisseurs.
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(),
provideBrowserGlobalErrorListeners(),
provideZonelessChangeDetection(),
provideRouter(routes)
]
};
Ensuite, nous définirons un signal pour stocker le texte de l’invite et créer une fonction pour définir sa valeur.
private promptSignal = signal<string>('');
setPrompt(prompt: string) {
this.promptSignal.set(prompt);
}
Ensuite, utilisons la nouvelle fonctionnalité d’Angular Version 20 L’API HTTPRESORCE pour faire un appel au point de terminaison de l’API OpenAI. Dans la section d’autorisation, nous passons la clé API et choisissons gpt-3.5-turbo
comme le modèle.
responseResource = httpResource<any>(() => ({
url: this.apiUrl + '/chat/completions',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`
},
body: {
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: this.promptSignal() }]
}
}));
En savoir plus sur le API httpresource.
Ajout de composant
Nous utiliserons le service dans le composant et créerons l’interface utilisateur. Exécutez la commande CLI suivante:
ng g c openaichat
Dans le composant, nous commençons par injecter le service et définir des variables pour capturer l’entrée de l’utilisateur en tant que signal et gérer la réponse de l’API.
prompt = signal("What is Angular ?");
openaiservice = inject(OpenAi);
response: any;
Ensuite, définissez une fonction pour récupérer la réponse de l’API.
getResponse() {
this.response = this.openaiservice.setPrompt(this.prompt());
}
Ajoutez un champ de saisie dans le modèle de composant pour recevoir l’entrée utilisateur.
<label for="prompt">Enter your question:</label>
<input
id="prompt"
type="text"
[value]="prompt()"
(input)="prompt.set($any($event.target).value)"
placeholder="Ask me anything..."
/>
Dans le code ci-dessus:
- Le
(input)
La liaison des événements est utilisée pour écouter les modifications en temps réel de la valeur de l’élément d’entrée. - Lorsque l’événement tire, le
set()
La méthode est appelée pour mettre à jour le signal rapide. $any($event.target)
Lance la cible de l’événement à n’importe quel, en contournant la vérification du type strict de TypeScript.
Ensuite, ajoutez un bouton qui déclenche le getResponse()
Fonction pour récupérer la réponse de l’invite d’OpenAI. Cette fonction a été implémentée dans la section précédente.
<button (click)="getResponse()">
Get Regular Response
</button>
Ensuite, affichez la réponse à l’intérieur d’un <p>
élément comme indiqué ci-dessous.
@if (openaiservice.responseResource.value()?.choices?.[0]?.message?.content) {
<p>{{ openaiservice.responseResource.value().choices[0].message.content }}</p>
} @else {
<p class="placeholder">No regular response yet...</p>
}
Jusqu’à présent, nous avons terminé toutes les étapes. Lorsque vous exécutez la demande, vous devriez recevoir une réponse du modèle OpenAI GPT-3.5-Turbo pour l’invite soumise.
Travailler avec la réponse en streaming
Les modèles OpenAI donnent deux types de réponses:
- Réponse régulière
- Réponse en streaming
Dans la mise en œuvre ci-dessus, nous avons géré une réponse régulière, où l’utilisateur attend que la réponse entière soit renvoyée en même temps. Cette approche peut sembler insensible ou moins engageante pour certains utilisateurs. Une alternative est une réponse de streaming, où OpenAI diffuse les données car le modèle génère chaque jeton.
Dans cette section, nous explorerons comment travailler avec les réponses en streaming. Pour y parvenir, lisez la clé API et l’URL à partir du fichier environnemental.
private apiKey = environment.openaiApiKey;
private apiUrl = environment.openaiApiUrl;
Ensuite, définissez un signal pour maintenir la réponse en streaming et créer une fonction Getter correspondante pour l’exposer en lecture seule. Ce Getter sera utilisé dans le modèle de composant pour afficher la réponse.
private streamingResponseSignal = signal<string>('');
get streamingResponse() {
return this.streamingResponseSignal.asReadonly();
}
Ensuite, créez une fonction pour envoyer une demande à OpenAI.
async streamChatCompletion(prompt: string): Promise<void> { }
Cette fonction effectuera deux tâches principales:
- Envoyez une demande à Openai pour recevoir une réponse de streaming.
- Analyser le flux entrant et mettre à jour le
streamingResponseSignal
avec le contenu.
Pour effectuer la partie 1 et pour recevoir une réponse de streaming d’OpenAI, nous utilisons l’API Fetch et définissons la propriété Stream sur True, comme indiqué ci-dessous.
const response = await fetch(this.apiUrl + '/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`
},
body: JSON.stringify({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: prompt }],
stream: true
})
});
En tant que partie 2, nous effectuerons les tâches suivantes:
- Lisez le flux en utilisant le
getReader
. - Le décoder en utilisant le
TextDecoder
. - Ajoutez la ligne décodée au signal de réponse.
const reader = response.body?.getReader();
const decoder = new TextDecoder();
if (!reader) {
throw new Error('Failed to get response reader');
}
let accumulatedResponse = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') {
return;
}
try {
const parsed = JSON.parse(data);
const content = parsed.choices?.[0]?.delta?.content;
if (content) {
accumulatedResponse += content;
this.streamingResponseSignal.set(accumulatedResponse);
}
} catch (e) {
continue;
}
}
}
}
Ce code gère les réponses en streaming renvoyées sous forme de réponse HTTP en morceaux d’OpenAI.
- Il lit le corps de réponse en utilisant le
getReader()
. - Ensuite, il utilise
TextDecoder
Pour convertir les données binaires en une chaîne. - Ensuite, les morceaux sont divisés en lignes si elles commencent par
"data:"
. - Enfin, il analyse les données du contenu en utilisant
JSON.parse
.
Tout assembler, le service pour obtenir une réponse en streaming d’Openai devrait ressembler à ceci:
import { Injectable, signal } from '@angular/core';
import { environment } from '../environments/environment';
@Injectable({
providedIn: 'root'
})
export class StreamingChatService {
private apiKey = environment.openaiApiKey;
private apiUrl = environment.openaiApiUrl;
private streamingResponseSignal = signal<string>('');
get streamingResponse() {
return this.streamingResponseSignal.asReadonly();
}
async streamChatCompletion(prompt: string): Promise<void> {
this.streamingResponseSignal.set('');
try {
const response = await fetch(this.apiUrl + '/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`
},
body: JSON.stringify({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: prompt }],
stream: true
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const reader = response.body?.getReader();
const decoder = new TextDecoder();
if (!reader) {
throw new Error('Failed to get response reader');
}
let accumulatedResponse = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') {
return;
}
try {
const parsed = JSON.parse(data);
const content = parsed.choices?.[0]?.delta?.content;
if (content) {
accumulatedResponse += content;
this.streamingResponseSignal.set(accumulatedResponse);
}
} catch (e) {
continue;
}
}
}
}
} catch (error) {
console.error('Streaming error:', error);
this.streamingResponseSignal.set('Error occurred while streaming response');
}
}
}
Dans le composant, définissez une nouvelle fonction pour récupérer la réponse de streaming.
async getStreamingResponse() {
this.isStreaming.set(true);
await this.streamingService.streamChatCompletion(this.prompt());
this.isStreaming.set(false);
}
Sur le modèle, ajoutez un nouveau bouton pour obtenir la réponse de streaming.
<button (click)="getStreamingResponse()" [disabled]="isStreaming()">
{{ isStreaming() ? 'Streaming...' : 'Get Streaming Response' }}
</button>
Ensuite, affichez la réponse à l’intérieur d’un <p>
élément comme indiqué ci-dessous.
@if (streamingService.streamingResponse()) {
<p>{{ streamingService.streamingResponse() }}</p>
} @else {
<p class="placeholder">No streaming response yet...</p>
}
Nous avons maintenant terminé toutes les étapes. Lorsque vous exécutez l’application, vous devriez recevoir une réponse de streaming du modèle Openai GPT-3.5-Turbo pour l’invite donnée.
J’espère que vous trouverez facile d’incorporer le modèle OpenAI dans votre application angulaire et qu’il ouvre de nombreuses nouvelles possibilités pour vos projets.
Source link