Spaces:
Running
Running
Commit
โข
8a302ab
1
Parent(s):
2caa135
Add application files
Browse files- Dockerfile +18 -0
- botree-404708-b377977f1aa4.json +13 -0
- main.py +158 -0
- requirements.text +7 -0
Dockerfile
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Use an official Python runtime as a base image
|
2 |
+
FROM python:3.10.9
|
3 |
+
|
4 |
+
# Set the working directory in the container
|
5 |
+
WORKDIR /
|
6 |
+
|
7 |
+
# Copy the current directory contents into the container at /app
|
8 |
+
COPY . .
|
9 |
+
|
10 |
+
# Install any needed dependencies specified in requirements.txt
|
11 |
+
RUN pip install --no-cache-dir --upgrade -r /requirements.txt
|
12 |
+
|
13 |
+
# Make port 80 available to the world outside this container
|
14 |
+
EXPOSE 80
|
15 |
+
|
16 |
+
# Define the command to run your FastAPI application
|
17 |
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
|
18 |
+
|
botree-404708-b377977f1aa4.json
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"type": "service_account",
|
3 |
+
"project_id": "botree-404708",
|
4 |
+
"private_key_id": "b377977f1aa45154144b3049c8f57594837db9c7",
|
5 |
+
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDMjTPHN8a2SwhB\nGfkxwiQQUsL785aaIJacSBKBkGuoV13UNmSnzU4UoC9HOZ28ue1QcG8+nrRSe/UT\nny3hnD4usN/ulnvyvzzAnsz6UKrd/zJfJ05If1X2sa+elKDINKkpLn6uns9W68ur\npDx6n1oNl/5iBuch8pFcjeJXo660MZBaidZWWqqGAoCTzXE8e+4LU2lSKv+tsYoK\n+yVKGNUrB/v4DXtw7eU27Hero9G2BLZhYIjbEvejmZ/URM6v3MsrQRWeqOurVLpp\nCORZHlecO5cvGzhOdCzqJiEM4g7evprlsx7vQ0h8Q/hExbVdo9fpCUtW6/KjTfua\n4L9vE5fbAgMBAAECggEAFuEyafWkre49mZ6Qn46yHvtK4Qixj0LW5dsv6rsfN6Cy\nF5MP9i8CLU9vil149cusLkOtRclVrSY9VvkGlkY2NF3HZnYBnjji0D7S+aq9OgCZ\n/0ezu2s2z9W3KZtBUrOFOlx/ggO0eGn+iY/gzex2E7AtHYTdJJBvzvT13MyrtW7k\naJxv/3EIfExBSS5Xbwtug84gL0cYJBiY2b58ckd83jQpGHL2iR0oMj64TPSeAA8W\nEOdX9Z35vPW5jt3ArQtdGG0vWAPfYfsBp+FADDdUzg1rUEy/Dd/AFAmQ/40gFsfg\nu8/vIqAjPUmkVwm5q0hQPJ533wtyo6ZVV3EjOgDUtQKBgQD6142Fnt5zR+WIKWtC\nOQgSaxrbhgj6YOQdAnbxDRBwC69RVYjbU/VyDuSlPUe45Lx8TQCy2QBauD1tXTXE\ntDY1G3V9Tmwc55HDmAGJ/9N4uO9p8OrlzA4p+Gdh0T5VprO/YBReDeJE6WPBCT61\nErQAvU3iwpKF50yymXEZFbS6DQKBgQDQwflO4zULzgnHCYnr6elRZN11bL/kHe2S\n8oDhN9ld2hOPz3qV8rCjXtO3RczPpgcKHSAoz5gpd7KluVBBZRArc0witGNQOlPe\n4YzmP/XZ1ALYDyDkQSuAGMiTk1xatEfZa4J3zYQUuSwvdLpvVCysy20Gbdp+AA15\nNOUxfkOnhwKBgQCE+Xvml9+pETYWxo47nuwuh2THdviPcom67zGKe7h5DVi1LzjL\nvGhjPI3tIt1AoNFiu5dhODQ942l87mqwijAqWxIfiVE6yW+2VoCKXXoHh1IzwSll\nBJWFnk9/xWLcGPE0xIRHj+ihS3A8RuBdMTsHIVOGoEr4fTNlgn44JA+YiQKBgQC7\nzSVJsOEx44OsSYqIb4B0tvb8An+G6t2liwAinKmx4tQiVhcD+rap4k8421RrogNH\nN/iMfmV3OLXAnTvz+MVZMXpW5k1KCY8WPXcSVIwKEM8WLFX8whwuOx2GldVJzFGu\n6ScQPBUMx6FWd/6Y1PLz6HYGiKE9JTL5zXo60kpu1QKBgGDPkd+FgWkZp5JWAqwh\nEdK6R/AYWqCsM+d5SXpRpk067XYoASicZpF0JtBB8MDK+z682cY5Y0UUPgXXvE13\nBYX8x9XC8bxK3lRpomkEC4MZlvffXspdp/zeF6HfUnFZ9/lX8juduqqnEHzf7/KP\nnO7Ah6W1yBBT8OS1Qq2mOIGH\n-----END PRIVATE KEY-----\n",
|
6 |
+
"client_email": "botree-admin@botree-404708.iam.gserviceaccount.com",
|
7 |
+
"client_id": "105695796499118798313",
|
8 |
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
9 |
+
"token_uri": "https://oauth2.googleapis.com/token",
|
10 |
+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
11 |
+
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/botree-admin%40botree-404708.iam.gserviceaccount.com",
|
12 |
+
"universe_domain": "googleapis.com"
|
13 |
+
}
|
main.py
ADDED
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from fastapi import Request, FastAPI, BackgroundTasks
|
3 |
+
import gspread
|
4 |
+
import requests
|
5 |
+
import openai
|
6 |
+
|
7 |
+
# OpenAI API KEY
|
8 |
+
API_KEY = "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"
|
9 |
+
openai.api_key = API_KEY
|
10 |
+
|
11 |
+
|
12 |
+
# Chatbase API๋ฅผ ์ด์ฉํด ํ
์คํธ๋ฅผ ๋ณด๋ด๊ณ ์๋ต์ ๋ฐ๋ ํจ์
|
13 |
+
def getResponseFromChatbase(prompt):
|
14 |
+
url = "https://www.chatbase.co/api/v1/chat"
|
15 |
+
payload = {
|
16 |
+
"stream": False,
|
17 |
+
"temperature": 0,
|
18 |
+
"chatId": "6dMpdT5zPPS5ik9pKptsH",
|
19 |
+
"messages": [{"role": "user", "content": prompt}]
|
20 |
+
}
|
21 |
+
headers = {
|
22 |
+
"accept": "application/json",
|
23 |
+
"content-type": "application/json",
|
24 |
+
"authorization": "Bearer e81b355c-30cc-47ca-b9fa-deb33f7159ad"
|
25 |
+
}
|
26 |
+
response = requests.post(url, json=payload, headers=headers)
|
27 |
+
# Chatbase API ์๋ต์ ํํ์ ๋ฐ๋ผ ์ ์ ํ ํ๋๋ฅผ ๋ฐํ
|
28 |
+
# {"text":"์๋
ํ์ธ์! ์ด๋๋ผ๋์ AI์
๋๋ค. ์ด๋ค ๋์์ด ํ์ํ์ ๊ฐ์?"}
|
29 |
+
return response.json()['text']
|
30 |
+
|
31 |
+
|
32 |
+
def getResponseFromGooey(prompt):
|
33 |
+
url = "https://api.gooey.ai/v2/TextToSpeech/"
|
34 |
+
gooey_key = 'sk-lbYNmTYKFA7Fb0yP60QsB5huMHjBmyRAJ0kJeFZMdgifeAEN'
|
35 |
+
payload = {
|
36 |
+
"text_prompt": prompt,
|
37 |
+
"tts_provider": "ELEVEN_LABS",
|
38 |
+
"uberduck_voice_name": "the-rock",
|
39 |
+
"uberduck_speaking_rate": 1,
|
40 |
+
"google_voice_name": "en-IN-Wavenet-A",
|
41 |
+
"google_speaking_rate": 1,
|
42 |
+
"google_pitch": 0,
|
43 |
+
"bark_history_prompt": "en_speaker_0",
|
44 |
+
"elevenlabs_voice_name": None,
|
45 |
+
"elevenlabs_api_key": "c5fb99a2b25402f104d246379bcf819a",
|
46 |
+
"elevenlabs_voice_id": "SKwm0HLYsVDCM2ruvw2p",
|
47 |
+
"elevenlabs_model": "eleven_multilingual_v2",
|
48 |
+
"elevenlabs_stability": 0.5,
|
49 |
+
"elevenlabs_similarity_boost": 0.75,
|
50 |
+
"elevenlabs_style": 0,
|
51 |
+
"elevenlabs_speaker_boost": True,
|
52 |
+
}
|
53 |
+
headers = {
|
54 |
+
"accept": "application/json",
|
55 |
+
"content-type": "application/json",
|
56 |
+
"authorization": "Bearer " + gooey_key
|
57 |
+
}
|
58 |
+
response = requests.post(url, json=payload, headers=headers)
|
59 |
+
return response.json()['output']['audio_url']
|
60 |
+
|
61 |
+
|
62 |
+
# ๋ฉ์ธ์ง ์ ์ก์ ์ํ ํฌ๋งท ํจ์
|
63 |
+
def textResponseFormatKakao(bot_response):
|
64 |
+
response = {
|
65 |
+
'version': '2.0',
|
66 |
+
'template': {
|
67 |
+
'outputs': [{"simpleText": {"text": bot_response}}],
|
68 |
+
'quickReplies': []
|
69 |
+
}
|
70 |
+
}
|
71 |
+
return response
|
72 |
+
|
73 |
+
|
74 |
+
# ChatGPT์๊ฒ ์ง๋ฌธ/๋ต๋ณ ๋ฐ๊ธฐ
|
75 |
+
def getTextFromGPT(prompt):
|
76 |
+
text = 'You are a thoughtful assistant.'\
|
77 |
+
' Respond to all input in 25 words and answer in korean.'
|
78 |
+
messages_prompt = [{
|
79 |
+
"role": "system",
|
80 |
+
"content": text
|
81 |
+
}]
|
82 |
+
messages_prompt += [{"role": "user", "content": prompt}]
|
83 |
+
response = openai.ChatCompletion.create(model="gpt-3.5-turbo",
|
84 |
+
messages=messages_prompt)
|
85 |
+
message = response["choices"][0]["message"]["content"]
|
86 |
+
return message
|
87 |
+
|
88 |
+
|
89 |
+
def create_callback_request_kakao(prompt, serverType, callbackUrl):
|
90 |
+
if serverType == 'CHAT':
|
91 |
+
# OpenAI API/Chatbase ๋ก prompt๋ฅผ ๋์ ธ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ต๋๋ค.
|
92 |
+
bot_res = getResponseFromChatbase(prompt)
|
93 |
+
elif serverType == 'AUDIO':
|
94 |
+
# Gooey๋ก prompt๋ฅผ ๋์ ธ์ ์ค๋์ค ํ์ผ ๊ฒฝ๋ก๋ฅผ ๋ฐ์์ต๋๋ค.
|
95 |
+
bot_res = getResponseFromGooey(prompt)
|
96 |
+
|
97 |
+
# callbackUrl๋ก ๊ฒฐ๊ณผ๊ฐ์ post๋ฐฉ์์ผ๋ก ์ ์กํฉ๋๋ค.
|
98 |
+
headers = {'Content-Type': 'application/json; charset=utf-8'}
|
99 |
+
requests.post(
|
100 |
+
callbackUrl,
|
101 |
+
json=textResponseFormatKakao(bot_res),
|
102 |
+
headers=headers,
|
103 |
+
timeout=5
|
104 |
+
)
|
105 |
+
return ""
|
106 |
+
|
107 |
+
|
108 |
+
# FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ธ์คํด์ค ์์ฑ
|
109 |
+
app = FastAPI()
|
110 |
+
|
111 |
+
|
112 |
+
# ๋ฐฑ๊ทธ๋ผ์ด๋ ์ฒ๋ฆฌ: verymuchmorethanastronomically.tistory.com/18 ์ฐธ๊ณ .
|
113 |
+
@app.post("/chat2/", tags=["kakao"])
|
114 |
+
async def chat2(request: Request, background_tasks: BackgroundTasks,):
|
115 |
+
# await ์ฒ๋ฆฌํ์ง ์์ผ๋ฉด userRequest๋ฅผ ์ฝ๋ค๊ฐ ์๋ฌ๊ฐ ๋ฐ์๋ฉ๋๋ค.
|
116 |
+
kakao_request = await request.json()
|
117 |
+
|
118 |
+
# /ask, /img, /gs ์ฒ๋ฆฌ.
|
119 |
+
if '/gs' in kakao_request["userRequest"]["utterance"]:
|
120 |
+
question = kakao_request["userRequest"]["utterance"].replace("/gs", "")
|
121 |
+
# json ํ์ผ์ด ์์นํ ๊ฒฝ๋ก๋ฅผ ๊ฐ์ผ๋ก ์ค์ผ ํฉ๋๋ค.
|
122 |
+
json_file_path = "botree-404708-b377977f1aa4.json"
|
123 |
+
gc = gspread.service_account(json_file_path)
|
124 |
+
sheet = 'https://docs.google.com/spreadsheets/d/'\
|
125 |
+
'1Iq5N59xU725bmxas730B_UQYZvX4EK_0rnRL-egxl_I/edit?usp=sharing'
|
126 |
+
doc = gc.open_by_url(sheet)
|
127 |
+
worksheet = doc.worksheet("์ํธ1")
|
128 |
+
|
129 |
+
# ์ด์ ์ ์
๋ ฅ๋ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒฝ์ฐ ๋ง์ง๋ง ํ์ ์ฐพ์์ ๋ค์ ํ์ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐ
|
130 |
+
last_row = len(worksheet.col_values(1)) + 1
|
131 |
+
cell = f'A{last_row}'
|
132 |
+
|
133 |
+
# ์ฌ์ฉ์๊ฐ ์ฑ๋ด์ ์
๋ ฅํ ๊ฐ์ ํด๋น ์ด์ ๋ฃ์ด์ค๋๋ค.
|
134 |
+
worksheet.update(cell, question)
|
135 |
+
return textResponseFormatKakao(f"{cell}์ ์์ฑ ์๋ฃ.")
|
136 |
+
elif '/sp' in kakao_request["userRequest"]["utterance"]:
|
137 |
+
prompt = kakao_request["userRequest"]["utterance"].replace("/sp", "")
|
138 |
+
type = 'AUDIO'
|
139 |
+
elif 'ask' in kakao_request['userRequest']['utterance']:
|
140 |
+
prompt = kakao_request["userRequest"]["utterance"].replace("/ask", "")
|
141 |
+
type = 'CHAT'
|
142 |
+
|
143 |
+
# ํ
์คํธ์ ๊ธธ์ด๊ฐ 10์ ์ด์ 200์ ์ดํ์ธ์ง ํ์ธ
|
144 |
+
length = len(kakao_request["userRequest"]["utterance"])
|
145 |
+
if length < 5 or length > 200:
|
146 |
+
return textResponseFormatKakao("์ง๋ฌธ์ 5์ ์ด์ 200์ ์ดํ๋ก ์
๋ ฅํด์ฃผ์ธ์")
|
147 |
+
|
148 |
+
# ๋ฐฑ๊ทธ๋ผ์ด๋๋ก ์นด์นด์ค ์ฑ๋ด์๊ฒ ์๋ต์ ๋ณด๋
๋๋ค.
|
149 |
+
background_tasks.add_task(
|
150 |
+
create_callback_request_kakao,
|
151 |
+
prompt=prompt,
|
152 |
+
serverType=type,
|
153 |
+
callbackUrl=kakao_request["userRequest"]["callbackUrl"],
|
154 |
+
)
|
155 |
+
|
156 |
+
# user_requests[user_id] += 1
|
157 |
+
# useCallback์ true์ฒ๋ฆฌํด์ค์ผ ์นด์นด์ค์์ 1๋ถ๊ฐ callbackUrl์ ์ ํจํ์ํต๋๋ค.
|
158 |
+
return {"version": "2.0", "useCallback": True}
|
requirements.text
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
fastapi
|
2 |
+
uvicorn
|
3 |
+
requests
|
4 |
+
jinja2
|
5 |
+
aiofiles
|
6 |
+
gspread
|
7 |
+
openai
|