Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -5,6 +5,9 @@ import re
|
|
5 |
import asyncio
|
6 |
from huggingface_hub import InferenceClient
|
7 |
from googleapiclient.discovery import build
|
|
|
|
|
|
|
8 |
from youtube_transcript_api import YouTubeTranscriptApi
|
9 |
from youtube_transcript_api.formatters import TextFormatter
|
10 |
from dotenv import load_dotenv
|
@@ -25,9 +28,28 @@ intents.guild_messages = True
|
|
25 |
# ์ถ๋ก API ํด๋ผ์ด์ธํธ ์ค์
|
26 |
hf_client = InferenceClient("CohereForAI/c4ai-command-r-plus", token=os.getenv("HF_TOKEN"))
|
27 |
|
28 |
-
# YouTube API ํค ์ค์
|
29 |
YOUTUBE_API_KEY = os.getenv("YOUTUBE_API_KEY")
|
30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
|
32 |
# ํน์ ์ฑ๋ ID
|
33 |
SPECIFIC_CHANNEL_ID = int(os.getenv("DISCORD_CHANNEL_ID"))
|
@@ -61,6 +83,7 @@ class MyClient(discord.Client):
|
|
61 |
if comments and transcript:
|
62 |
replies = await generate_replies(comments, transcript)
|
63 |
await create_thread_and_send_replies(message, video_id, comments, replies)
|
|
|
64 |
else:
|
65 |
await message.channel.send("์๋ง์ด๋ ๋๊ธ์ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.")
|
66 |
else:
|
@@ -131,7 +154,8 @@ async def get_video_comments(video_id):
|
|
131 |
|
132 |
for item in response.get('items', []):
|
133 |
comment = item['snippet']['topLevelComment']['snippet']['textOriginal']
|
134 |
-
|
|
|
135 |
|
136 |
logging.debug(f'Fetched comments: {comments}')
|
137 |
return comments
|
@@ -141,15 +165,15 @@ async def generate_replies(comments, transcript):
|
|
141 |
๋๊ธ๊ณผ ์๋ง์ ๊ธฐ๋ฐ์ผ๋ก LLM ๋ต๊ธ์ ์์ฑํฉ๋๋ค.
|
142 |
"""
|
143 |
replies = []
|
144 |
-
for comment in comments:
|
145 |
messages = [
|
146 |
{"role": "system", "content": f"๋น๋์ค ์๋ง: {transcript}"},
|
147 |
{"role": "user", "content": comment}
|
148 |
]
|
149 |
loop = asyncio.get_event_loop()
|
150 |
response = await loop.run_in_executor(None, lambda: hf_client.chat_completion(
|
151 |
-
messages, max_tokens=
|
152 |
-
|
153 |
if response.choices and response.choices[0].message:
|
154 |
reply = response.choices[0].message['content'].strip()
|
155 |
else:
|
@@ -164,10 +188,29 @@ async def create_thread_and_send_replies(message, video_id, comments, replies):
|
|
164 |
๋๊ธ๊ณผ ๋ต๊ธ์ ์๋ก์ด ์ฐ๋ ๋์ ์ ์กํฉ๋๋ค.
|
165 |
"""
|
166 |
thread = await message.channel.create_thread(name=f"{message.author.name}์ ๋๊ธ ๋ต๊ธ", message=message)
|
167 |
-
for comment, reply in zip(comments, replies):
|
168 |
embed = discord.Embed(description=f"**๋๊ธ**: {comment}\n**๋ต๊ธ**: {reply}")
|
169 |
await thread.send(embed=embed)
|
170 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
if __name__ == "__main__":
|
172 |
discord_client = MyClient(intents=intents)
|
173 |
discord_client.run(os.getenv('DISCORD_TOKEN'))
|
|
|
5 |
import asyncio
|
6 |
from huggingface_hub import InferenceClient
|
7 |
from googleapiclient.discovery import build
|
8 |
+
from google.oauth2.credentials import Credentials
|
9 |
+
from google_auth_oauthlib.flow import InstalledAppFlow
|
10 |
+
from google.auth.transport.requests import Request
|
11 |
from youtube_transcript_api import YouTubeTranscriptApi
|
12 |
from youtube_transcript_api.formatters import TextFormatter
|
13 |
from dotenv import load_dotenv
|
|
|
28 |
# ์ถ๋ก API ํด๋ผ์ด์ธํธ ์ค์
|
29 |
hf_client = InferenceClient("CohereForAI/c4ai-command-r-plus", token=os.getenv("HF_TOKEN"))
|
30 |
|
31 |
+
# YouTube API ํค ์ค์ ๋ฐ OAuth 2.0 ์ธ์ฆ ์ค์
|
32 |
YOUTUBE_API_KEY = os.getenv("YOUTUBE_API_KEY")
|
33 |
+
SCOPES = ["https://www.googleapis.com/auth/youtube.force-ssl"]
|
34 |
+
creds = None
|
35 |
+
|
36 |
+
# ํ๊ฒฝ๋ณ์ ์ค์ (ํ ํฐ์ ์ ์ฅํ ํ์ผ ๊ฒฝ๋ก)
|
37 |
+
TOKEN_PATH = 'token.json'
|
38 |
+
CREDENTIALS_PATH = 'credentials.json'
|
39 |
+
|
40 |
+
if os.path.exists(TOKEN_PATH):
|
41 |
+
creds = Credentials.from_authorized_user_file(TOKEN_PATH, SCOPES)
|
42 |
+
if not creds or not creds.valid:
|
43 |
+
if creds and creds.expired and creds.refresh_token:
|
44 |
+
creds.refresh(Request())
|
45 |
+
else:
|
46 |
+
flow = InstalledAppFlow.from_client_secrets_file(
|
47 |
+
CREDENTIALS_PATH, SCOPES)
|
48 |
+
creds = flow.run_local_server(port=0)
|
49 |
+
with open(TOKEN_PATH, 'w') as token:
|
50 |
+
token.write(creds.to_json())
|
51 |
+
|
52 |
+
youtube_service = build('youtube', 'v3', credentials=creds)
|
53 |
|
54 |
# ํน์ ์ฑ๋ ID
|
55 |
SPECIFIC_CHANNEL_ID = int(os.getenv("DISCORD_CHANNEL_ID"))
|
|
|
83 |
if comments and transcript:
|
84 |
replies = await generate_replies(comments, transcript)
|
85 |
await create_thread_and_send_replies(message, video_id, comments, replies)
|
86 |
+
await post_replies_to_youtube(video_id, comments, replies)
|
87 |
else:
|
88 |
await message.channel.send("์๋ง์ด๋ ๋๊ธ์ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.")
|
89 |
else:
|
|
|
154 |
|
155 |
for item in response.get('items', []):
|
156 |
comment = item['snippet']['topLevelComment']['snippet']['textOriginal']
|
157 |
+
comment_id = item['snippet']['topLevelComment']['id']
|
158 |
+
comments.append((comment, comment_id)) # ๋๊ธ๊ณผ ๋๊ธ ID๋ฅผ ํจ๊ป ์ ์ฅ
|
159 |
|
160 |
logging.debug(f'Fetched comments: {comments}')
|
161 |
return comments
|
|
|
165 |
๋๊ธ๊ณผ ์๋ง์ ๊ธฐ๋ฐ์ผ๋ก LLM ๋ต๊ธ์ ์์ฑํฉ๋๋ค.
|
166 |
"""
|
167 |
replies = []
|
168 |
+
for comment, _ in comments:
|
169 |
messages = [
|
170 |
{"role": "system", "content": f"๋น๋์ค ์๋ง: {transcript}"},
|
171 |
{"role": "user", "content": comment}
|
172 |
]
|
173 |
loop = asyncio.get_event_loop()
|
174 |
response = await loop.run_in_executor(None, lambda: hf_client.chat_completion(
|
175 |
+
messages, max_tokens=400, temperature=0.7, top_p=0.85)) # max_tokens ๊ฐ์ ์กฐ์
|
176 |
+
|
177 |
if response.choices and response.choices[0].message:
|
178 |
reply = response.choices[0].message['content'].strip()
|
179 |
else:
|
|
|
188 |
๋๊ธ๊ณผ ๋ต๊ธ์ ์๋ก์ด ์ฐ๋ ๋์ ์ ์กํฉ๋๋ค.
|
189 |
"""
|
190 |
thread = await message.channel.create_thread(name=f"{message.author.name}์ ๋๊ธ ๋ต๊ธ", message=message)
|
191 |
+
for (comment, _), reply in zip(comments, replies):
|
192 |
embed = discord.Embed(description=f"**๋๊ธ**: {comment}\n**๋ต๊ธ**: {reply}")
|
193 |
await thread.send(embed=embed)
|
194 |
|
195 |
+
async def post_replies_to_youtube(video_id, comments, replies):
|
196 |
+
"""
|
197 |
+
์์ฑ๋ ๋ต๊ธ์ YouTube ๋๊ธ๋ก ๊ฒ์ํฉ๋๋ค.
|
198 |
+
"""
|
199 |
+
for (comment, comment_id), reply in zip(comments, replies):
|
200 |
+
try:
|
201 |
+
youtube_service.comments().insert(
|
202 |
+
part='snippet',
|
203 |
+
body={
|
204 |
+
'snippet': {
|
205 |
+
'parentId': comment_id,
|
206 |
+
'textOriginal': reply
|
207 |
+
}
|
208 |
+
}
|
209 |
+
).execute()
|
210 |
+
logging.debug(f'Posted reply to comment: {comment_id}')
|
211 |
+
except Exception as e:
|
212 |
+
logging.error(f'Error posting reply to comment {comment_id}: {e}')
|
213 |
+
|
214 |
if __name__ == "__main__":
|
215 |
discord_client = MyClient(intents=intents)
|
216 |
discord_client.run(os.getenv('DISCORD_TOKEN'))
|