from fastapi import Request, FastAPI, BackgroundTasks import gspread import requests import openai # OpenAI API KEY API_KEY = "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" openai.api_key = API_KEY # Chatbase API를 이용해 텍스트를 보내고 응답을 받는 함수 def getResponseFromChatbase(prompt): url = "https://www.chatbase.co/api/v1/chat" payload = { "stream": False, "temperature": 0, "chatId": "6dMpdT5zPPS5ik9pKptsH", "messages": [{"role": "user", "content": prompt}] } headers = { "accept": "application/json", "content-type": "application/json", "authorization": "Bearer e81b355c-30cc-47ca-b9fa-deb33f7159ad" } response = requests.post(url, json=payload, headers=headers) # Chatbase API 응답의 형태에 따라 적절한 필드를 반환 # {"text":"안녕하세요! 이나라도움 AI입니다. 어떤 도움이 필요하신가요?"} return response.json()['text'] def getResponseFromGooey(prompt): url = "https://api.gooey.ai/v2/TextToSpeech/" gooey_key = 'sk-lbYNmTYKFA7Fb0yP60QsB5huMHjBmyRAJ0kJeFZMdgifeAEN' payload = { "text_prompt": prompt, "tts_provider": "ELEVEN_LABS", "uberduck_voice_name": "the-rock", "uberduck_speaking_rate": 1, "google_voice_name": "en-IN-Wavenet-A", "google_speaking_rate": 1, "google_pitch": 0, "bark_history_prompt": "en_speaker_0", "elevenlabs_voice_name": None, "elevenlabs_api_key": "c5fb99a2b25402f104d246379bcf819a", "elevenlabs_voice_id": "SKwm0HLYsVDCM2ruvw2p", "elevenlabs_model": "eleven_multilingual_v2", "elevenlabs_stability": 0.5, "elevenlabs_similarity_boost": 0.75, "elevenlabs_style": 0, "elevenlabs_speaker_boost": True, } headers = { "accept": "application/json", "content-type": "application/json", "authorization": "Bearer " + gooey_key } response = requests.post(url, json=payload, headers=headers) return response.json()['output']['audio_url'] # 메세지 전송을 위한 포맷 함수 def textResponseFormatKakao(bot_response): response = { 'version': '2.0', 'template': { 'outputs': [{"simpleText": {"text": bot_response}}], 'quickReplies': [] } } return response # ChatGPT에게 질문/답변 받기 def getTextFromGPT(prompt): text = 'You are a thoughtful assistant.'\ ' Respond to all input in 25 words and answer in korean.' messages_prompt = [{ "role": "system", "content": text }] messages_prompt += [{"role": "user", "content": prompt}] response = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=messages_prompt) message = response["choices"][0]["message"]["content"] return message def create_callback_request_kakao(prompt, serverType, callbackUrl): if serverType == 'CHAT': # OpenAI API/Chatbase 로 prompt를 던져서 결과를 받아옵니다. bot_res = getResponseFromChatbase(prompt) elif serverType == 'AUDIO': # Gooey로 prompt를 던져서 오디오 파일 경로를 받아옵니다. bot_res = getResponseFromGooey(prompt) # callbackUrl로 결과값을 post방식으로 전송합니다. headers = {'Content-Type': 'application/json; charset=utf-8'} requests.post( callbackUrl, json=textResponseFormatKakao(bot_res), headers=headers, timeout=5 ) return "" # FastAPI 애플리케이션 인스턴스 생성 app = FastAPI() # 백그라운드 처리: verymuchmorethanastronomically.tistory.com/18 참고. @app.post("/chat2/", tags=["kakao"]) async def chat2(request: Request, background_tasks: BackgroundTasks,): # await 처리하지 않으면 userRequest를 읽다가 에러가 발생됩니다. kakao_request = await request.json() # /ask, /img, /gs 처리. if '/gs' in kakao_request["userRequest"]["utterance"]: question = kakao_request["userRequest"]["utterance"].replace("/gs", "") # json 파일이 위치한 경로를 값으로 줘야 합니다. json_file_path = "botree-404708-b377977f1aa4.json" gc = gspread.service_account(json_file_path) sheet = 'https://docs.google.com/spreadsheets/d/'\ '1Iq5N59xU725bmxas730B_UQYZvX4EK_0rnRL-egxl_I/edit?usp=sharing' doc = gc.open_by_url(sheet) worksheet = doc.worksheet("시트1") # 이전에 입력된 데이터가 있는 경우 마지막 행을 찾아서 다음 행에 데이터를 추가 last_row = len(worksheet.col_values(1)) + 1 cell = f'A{last_row}' # 사용자가 챗봇에 입력한 값을 해당 열에 넣어줍니다. worksheet.update(cell, question) return textResponseFormatKakao(f"{cell}에 작성 완료.") elif '/sp' in kakao_request["userRequest"]["utterance"]: prompt = kakao_request["userRequest"]["utterance"].replace("/sp", "") type = 'AUDIO' elif 'ask' in kakao_request['userRequest']['utterance']: prompt = kakao_request["userRequest"]["utterance"].replace("/ask", "") type = 'CHAT' # 텍스트의 길이가 10자 이상 200자 이하인지 확인 length = len(kakao_request["userRequest"]["utterance"]) if length < 5 or length > 200: return textResponseFormatKakao("질문은 5자 이상 200자 이하로 입력해주세요") # 백그라운드로 카카오 챗봇에게 응답을 보냅니다. background_tasks.add_task( create_callback_request_kakao, prompt=prompt, serverType=type, callbackUrl=kakao_request["userRequest"]["callbackUrl"], ) # user_requests[user_id] += 1 # useCallback을 true처리해줘야 카카오에서 1분간 callbackUrl을 유효화시킵니다. return {"version": "2.0", "useCallback": True}