Django Rest Framework ve ChatGPT API Entegrasyonu¶
Bu yazımızda Django Rest Framework ile basit bir API geliştirecek ve ChatGPT API'ya (openai API) istek atıp chatGPT'ye gönderilen kodun hangi programlama diline ait olduğunu söylemesini isteyeceğiz.
Kurulumlar¶
drf_chatgpt adında bir klasör oluşturduktan sonra aşağıdaki komutlar ile sanal ortam oluşturup aktif edelim
- Aşağıdaki komutlar ile proje için gerekli paketleri kuralım - Kurulan paketleri dosyaya yazalımDjango Projesi Oluşturma¶
- api adında django app oluşturma - src/settings.py dosyasında harici(externals) ve dahili(internals) uygulamaların eklenmesiINSTALLED_APPS = [
# external apps
'rest_framework',
'rest_framework.authtoken',
# internal apps
'api',
# default apps
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
import os
from pathlib import Path
from dotenv import load_dotenv
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
load_dotenv(os.path.join(BASE_DIR, '.env'))
APIKEY = os.getenv("OPENAI_APIKEY")
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
from django.db import models
class CodeExplainer(models.Model):
_input = models.TextField()
_output = models.TextField()
class Meta:
db_table = "t_code_explainer"
Migrationların yapılması¶
- superuser oluşturmaChatGPT OpenAI API ile Etkileşim¶
api/utils.py oluşturulması ve düzenlenmesi
import openai
from django.conf import settings
openai.api_key = settings.APIKEY
def send_code_to_api(code):
try:
res = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "user", "content": f"Tell me what language is this code written? {code}"},
{"role": "system", "content": "You are a helpful assistant that provides code explanations."},
{"role": "assistant", "content": "Sure! Please provide the code you want me to explain."}
],
)
return res["choices"][0]["message"]["content"]
except openai.error.APIError as e:
raise ValueError(f"OpenAI API returned an API Error: {e}")
except openai.error.APIConnectionError as e:
raise ValueError(f"Failed to connect to OpenAI API: {e}")
except openai.error.RateLimitError as e:
raise ValueError(f"OpenAI API request exceeded rate limit: {e}")
OpenAI dökümantasyonundan bir örnek istek ve api response¶
import openai
openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who won the world series in 2020?"},
{"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
{"role": "user", "content": "Where was it played?"}
]
)
{
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "The 2020 World Series was played in Texas at Globe Life Field in Arlington.",
"role": "assistant"
}
}
],
"created": 1677664795,
"id": "chatcmpl-7QyqpwdfhqwajicIEznoc6Q47XAyW",
"model": "gpt-3.5-turbo-0613",
"object": "chat.completion",
"usage": {
"completion_tokens": 17,
"prompt_tokens": 57,
"total_tokens": 74
}
}
from rest_framework import serializers
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
from rest_framework.authtoken.models import Token
# internals
from api.models import CodeExplainer
from api.utils import send_code_to_api
class CodeExplainSerializer(serializers.ModelSerializer):
"""
_output alanı chatGPT'den gelen response verisi ile doldurulacak
"""
class Meta:
model = CodeExplainer
fields = ("id","_input","_output")
extra_kwargs = {
"_output":{"read_only":True}
}
def create(self, validated_data):
ce = CodeExplainer(**validated_data)
# girilen _input degerini chatGPT'ye gonder ve gelen cevabı _output'a atama yap.
_output = send_code_to_api(validated_data["_input"])
ce._output = _output
ce.save()
return ce
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ("id", "username", "email", "password")
# parolayi sadece veriyi yazarken kullanacagiz bu yuzden write_only olmali
extra_kwargs = {
"password":{"write_only":True}
}
def create(self, validated_data):
password = validated_data.pop("password")
user = User.objects.create(**validated_data)
# parolayi kriptolu bir sekilde kaydetmek icin set_password kullanilmalidir
user.set_password(password)
user.save()
# olusturulan kullanıci icin bir tane de token objesi oluşturuluyor
Token.objects.create(user=user)
return user
class TokenSerializer(serializers.Serializer):
"""Token oluşturmak icin username ve password alanlari gereklidir"""
username = serializers.CharField()
password = serializers.CharField(style={"input_type":"password"},trim_whitespace=False)
def validate(self, attrs):
username = attrs.get("username")
password = attrs.get("password")
# verilen username ve password ile yetkilendirme islemi yapilir
user = authenticate(request=self.context.get("request"),username=username, password=password)
# kullanıcı authenticate olamazsa dogrulama hatasi uretilir
if not user:
msg = "Credentials are not provided correctly..."
raise serializers.ValidationError(msg, code="authentication")
# kullanici authenticate olmussa attrs'e kaydedilir
attrs["user"] = user
return attrs
from rest_framework import views, status
from rest_framework.response import Response
from django.contrib.auth.models import User
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import AllowAny
# internals
from api.serializers import CodeExplainSerializer, UserSerializer, TokenSerializer
from api.models import CodeExplainer
class CodeExplainView(views.APIView):
serializer_class = CodeExplainSerializer
# kullanici code-explain endpointi kullanabilmek icin token almalidir
authentication_classes = [TokenAuthentication]
def get(self, request, format=None):
qs = CodeExplainer.objects.all()
serializer = self.serializer_class(qs, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class UserView(views.APIView):
serializer_class = UserSerializer
permission_classes = [AllowAny]
def post(self, request, format=None):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class TokenView(ObtainAuthToken):
serializer_class = TokenSerializer
from django.urls import path
# internals
from api.views import UserView, TokenView, CodeExplainView
urlpatterns = [
path('users/', UserView.as_view(), name='users'),
path('tokens/', TokenView.as_view(), name='tokens'),
path('code-explain/', CodeExplainView.as_view(), name='code-explain' )
]
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include('api.urls'))
]
Projenin Çalıştırılması¶
Endpointlerin Test Edilmesi¶
curl, postman, thunder client gibi araçlar ile geliştirdiğimiz API'yı test edebiliriz.
- "users"
http://127.0.0.1:8000/api/v1/users/ adresine aşağıdaki istek gövdesi(request body) ile POST request gönderelim
- API response - 2. "tokens"Oluşturduğumuz kullanıcının username ve password bilgisi ile token oluşturalım
http://127.0.0.1:8000/api/v1/tokens/ adresine aşağıdaki request body ile POST request gönderelim
- API Response - 3. "code-explain"Aldığımız token ile http://127.0.0.1:8000/api/v1/code-explain/ adresine aşağıdaki request body ile POST request gönderelim
- API Response{
"id": 1,
"_input": "[i**2 for i in range(1,100) if i%2==0]",
"_output": "The code you provided is written in Python.\n\nIt is a list comprehension expression that generates a list of squares of even numbers from 1 to 99.\n\nLet's break it down:\n\n- `[i**2` is the expression that calculates the square of the current number.\n- `for i in range(1,100)` is the loop that iterates over the numbers from 1 to 99.\n- `if i%2==0]` is the condition that filters out only the even numbers.\n\nSo, the code calculates the square of each even number from 1 to 99 and returns a list containing these values."
}
{
"id": 2,
"_input": "fmt.Print('Hello world')",
"_output": "The code you provided appears to be written in Go (often referred to as Golang). In this particular example, the code uses the `fmt` package from the Go standard library to print the string \"Hello world\" to the standard output."
}
Daha fazla yapay zeka API'ları ile etkileşime geçmek, web uygulamalarına nasıl entegre edileceğini öğrenmek için takipte kalın...