├── first_app ├── __init__.py ├── migrations │ ├── __init__.py │ └── 0001_initial.py ├── tests.py ├── admin.py ├── apps.py ├── models.py ├── templates │ └── first_app │ │ ├── hello_model.html │ │ ├── hello_template.html │ │ └── index.html ├── urls.py ├── forms.py ├── views.py └── utils.py ├── chatgpt_project ├── __init__.py ├── asgi.py ├── wsgi.py ├── urls.py └── settings.py ├── .gitignore ├── 20231108 Django with Azure AI.pdf ├── .env ├── README.md └── manage.py /first_app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chatgpt_project/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /first_app/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | .pytest_cache/ 3 | .venv/ 4 | .vscode/ 5 | db.sqlite3 6 | -------------------------------------------------------------------------------- /first_app/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /20231108 Django with Azure AI.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ko-Ko-Kirk/mwc2023_django_with_aoai/HEAD/20231108 Django with Azure AI.pdf -------------------------------------------------------------------------------- /first_app/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from first_app.models import StoryModel 3 | # Register your models here. 4 | admin.site.register(StoryModel) -------------------------------------------------------------------------------- /first_app/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FirstAppConfig(AppConfig): 5 | default_auto_field = "django.db.models.BigAutoField" 6 | name = "first_app" 7 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | OPENAI_API_TYPE=azure 2 | OPENAI_API_BASE=https://XXX.openai.azure.com/ 3 | OPENAI_API_VERSION=2023-08-01-preview 4 | OPENAI_API_KEY=yourkey 5 | AZURE_SPEECH_KEY=yourkey 6 | AZURE_SPEECH_REGION=yourregion -------------------------------------------------------------------------------- /first_app/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | class StoryModel(models.Model): 5 | id = models.AutoField(primary_key=True) 6 | text = models.TextField() 7 | path = models.TextField() -------------------------------------------------------------------------------- /first_app/templates/first_app/hello_model.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |{{ story }}
25 | {% endif %} 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /first_app/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | 4 | class StoryForm(forms.Form): 5 | ANIMAL_CHOICES = [ 6 | ('熊熊', '熊熊'), 7 | ('兔兔', '兔兔'), 8 | ('貓貓', '貓貓'), 9 | ('狗狗', '狗狗'), 10 | ] 11 | 12 | SCENE_RADIO = [ 13 | ('都市', '都市'), 14 | ('森林', '森林'), 15 | ('學校', '學校'), 16 | ('海邊', '海邊'), 17 | ] 18 | 19 | animals = forms.MultipleChoiceField( 20 | widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-control'}), choices=ANIMAL_CHOICES, 21 | label='選擇動物', 22 | ) 23 | 24 | scene = forms.ChoiceField( 25 | widget=forms.RadioSelect(attrs={'class': 'form-control'}), 26 | choices=SCENE_RADIO, 27 | label='選擇場景', 28 | ) 29 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "chatgpt_project.settings") 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == "__main__": 22 | main() 23 | -------------------------------------------------------------------------------- /chatgpt_project/urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | URL configuration for chatgpt_project project. 3 | 4 | The `urlpatterns` list routes URLs to views. For more information please see: 5 | https://docs.djangoproject.com/en/4.2/topics/http/urls/ 6 | Examples: 7 | Function views 8 | 1. Add an import: from my_app import views 9 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 10 | Class-based views 11 | 1. Add an import: from other_app.views import Home 12 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 13 | Including another URLconf 14 | 1. Import the include() function: from django.urls import include, path 15 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 16 | """ 17 | from django.contrib import admin 18 | from django.urls import include, path 19 | from django.conf.urls.static import static 20 | from django.conf import settings 21 | 22 | urlpatterns = [ 23 | path("", include("first_app.urls")), 24 | path('admin/', admin.site.urls) 25 | ] 26 | 27 | urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 28 | -------------------------------------------------------------------------------- /first_app/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from datetime import datetime 3 | from django.views import View 4 | from .forms import StoryForm 5 | from .utils import get_openai_response, send_to_tts 6 | 7 | from first_app.models import StoryModel 8 | from django.http import HttpResponse 9 | def home(request): 10 | return HttpResponse("Hello, Django!") 11 | 12 | def hello_template(request, name): 13 | return render( 14 | request, 15 | 'first_app/hello_template.html', 16 | { 17 | 'name': name, 18 | 'date': datetime.now() 19 | } 20 | ) 21 | 22 | def hello_model(request, id): 23 | return render( 24 | request, 25 | 'first_app/hello_model.html', 26 | { 27 | 'object': StoryModel.objects.get(id=id) 28 | } 29 | ) 30 | 31 | 32 | class StoryTellerView(View): 33 | template_name = 'first_app/index.html' 34 | 35 | def get(self, request): 36 | form = StoryForm() 37 | return render(request, self.template_name, {'form': form}) 38 | 39 | def post(self, request): 40 | form = StoryForm(request.POST) 41 | story = "" 42 | if form.is_valid(): 43 | selected_animals = form.cleaned_data['animals'] 44 | selected_animals_str = ', '.join(selected_animals) 45 | 46 | selected_scene = form.cleaned_data['scene'] 47 | 48 | story = get_openai_response(selected_animals_str + "在" + selected_scene + "。") 49 | 50 | audio_path = send_to_tts(story) 51 | 52 | StoryModel.objects.create( 53 | text=story, 54 | path=audio_path, 55 | ) 56 | 57 | 58 | return render(request, self.template_name, {'form': form, 'story': story, 'audio': audio_path}) 59 | -------------------------------------------------------------------------------- /first_app/utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import uuid 3 | 4 | from openai import AzureOpenAI 5 | import azure.cognitiveservices.speech as speechsdk 6 | from django.conf import settings 7 | 8 | speech_key, service_region = os.getenv("AZURE_SPEECH_KEY"), os.getenv("AZURE_SPEECH_REGION") 9 | 10 | 11 | def get_openai_response(prompt: str) -> str: 12 | 13 | client = AzureOpenAI( 14 | api_version=os.getenv("OPENAI_API_VERSION"), 15 | azure_endpoint=os.getenv("OPENAI_API_BASE"), 16 | api_key=os.getenv("OPENAI_API_KEY"), 17 | ) 18 | 19 | completion = client.chat.completions.create( 20 | model="jpchat35", # your deployment name 21 | messages=[{"role": "system", "content": "你是一個童話故事作家,請幫我根據user的動物與場景,來編一個童話故事。"}, 22 | {"role": "user", "content": prompt}], 23 | temperature=0.7, 24 | max_tokens=2000, 25 | top_p=0.95, 26 | frequency_penalty=0, 27 | presence_penalty=0, 28 | stop=None 29 | ) 30 | 31 | return completion.choices[0].message.content 32 | 33 | 34 | def send_to_tts(story: str): 35 | speech_config = speechsdk.SpeechConfig(subscription=speech_key, 36 | region=service_region) 37 | speech_config.speech_synthesis_voice_name = "zh-TW-YunJheNeural" 38 | speech_config.speech_synthesis_language = "zh-TW" 39 | speech_config.set_speech_synthesis_output_format(speechsdk.SpeechSynthesisOutputFormat.Audio24Khz48KBitRateMonoMp3) 40 | 41 | audio_filename = uuid.uuid4().hex + ".mp4" 42 | static_path = os.path.join(settings.MEDIA_ROOT, audio_filename) 43 | 44 | audio_config = speechsdk.AudioConfig(filename=static_path) 45 | 46 | speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config) 47 | 48 | result = speech_synthesizer.speak_text_async(story).get() 49 | # Check result 50 | if result.reason == speechsdk.ResultReason.SynthesizingAudioCompleted: 51 | return f"{settings.MEDIA_URL}{audio_filename}" 52 | elif result.reason == speechsdk.ResultReason.Canceled: 53 | cancellation_details = result.cancellation_details 54 | print("Speech synthesis canceled: {}".format(cancellation_details.reason)) 55 | if cancellation_details.reason == speechsdk.CancellationReason.Error: 56 | print("Error details: {}".format(cancellation_details.error_details)) 57 | -------------------------------------------------------------------------------- /chatgpt_project/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for chatgpt_project project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.2.7. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.2/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.2/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | import dotenv 15 | import os 16 | 17 | dotenv.load_dotenv() 18 | 19 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 20 | BASE_DIR = Path(__file__).resolve().parent.parent 21 | 22 | 23 | # Quick-start development settings - unsuitable for production 24 | # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ 25 | 26 | # SECURITY WARNING: keep the secret key used in production secret! 27 | SECRET_KEY = "django-insecure-9zuzly6jl5_i^xzft-z2#x7o1l530xg5=ffq$%w+qdj5wurj!#" 28 | 29 | # SECURITY WARNING: don't run with debug turned on in production! 30 | DEBUG = True 31 | 32 | ALLOWED_HOSTS = [] 33 | 34 | 35 | # Application definition 36 | 37 | INSTALLED_APPS = [ 38 | "django.contrib.admin", 39 | "django.contrib.auth", 40 | "django.contrib.contenttypes", 41 | "django.contrib.sessions", 42 | "django.contrib.messages", 43 | "django.contrib.staticfiles", 44 | "first_app", 45 | ] 46 | 47 | MIDDLEWARE = [ 48 | "django.middleware.security.SecurityMiddleware", 49 | "django.contrib.sessions.middleware.SessionMiddleware", 50 | "django.middleware.common.CommonMiddleware", 51 | "django.middleware.csrf.CsrfViewMiddleware", 52 | "django.contrib.auth.middleware.AuthenticationMiddleware", 53 | "django.contrib.messages.middleware.MessageMiddleware", 54 | "django.middleware.clickjacking.XFrameOptionsMiddleware", 55 | ] 56 | 57 | ROOT_URLCONF = "chatgpt_project.urls" 58 | 59 | TEMPLATES = [ 60 | { 61 | "BACKEND": "django.template.backends.django.DjangoTemplates", 62 | "DIRS": [], 63 | "APP_DIRS": True, 64 | "OPTIONS": { 65 | "context_processors": [ 66 | "django.template.context_processors.debug", 67 | "django.template.context_processors.request", 68 | "django.contrib.auth.context_processors.auth", 69 | "django.contrib.messages.context_processors.messages", 70 | ], 71 | }, 72 | }, 73 | ] 74 | 75 | WSGI_APPLICATION = "chatgpt_project.wsgi.application" 76 | 77 | 78 | # Database 79 | # https://docs.djangoproject.com/en/4.2/ref/settings/#databases 80 | 81 | DATABASES = { 82 | "default": { 83 | "ENGINE": "django.db.backends.sqlite3", 84 | "NAME": BASE_DIR / "db.sqlite3", 85 | } 86 | } 87 | 88 | 89 | # Password validation 90 | # https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators 91 | 92 | AUTH_PASSWORD_VALIDATORS = [ 93 | { 94 | "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", 95 | }, 96 | {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",}, 97 | {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",}, 98 | {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",}, 99 | ] 100 | 101 | 102 | # Internationalization 103 | # https://docs.djangoproject.com/en/4.2/topics/i18n/ 104 | 105 | LANGUAGE_CODE = "en-us" 106 | 107 | TIME_ZONE = "UTC" 108 | 109 | USE_I18N = True 110 | 111 | USE_TZ = True 112 | 113 | 114 | # Static files (CSS, JavaScript, Images) 115 | # https://docs.djangoproject.com/en/4.2/howto/static-files/ 116 | 117 | STATIC_URL = "static/" 118 | MEDIA_URL = "/media/" 119 | MEDIA_ROOT = os.path.join(BASE_DIR, "media") 120 | # Default primary key field type 121 | # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field 122 | 123 | DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" 124 | --------------------------------------------------------------------------------