Spaces:
Sleeping
Sleeping
import discord | |
import logging | |
import os | |
import asyncio | |
import subprocess | |
from huggingface_hub import InferenceClient | |
from yahooquery import Ticker | |
from datetime import datetime | |
# ๋ก๊น ์ค์ | |
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s:%(levelname)s:%(name)s: %(message)s', handlers=[logging.StreamHandler()]) | |
# ์ธํ ํธ ์ค์ | |
intents = discord.Intents.default() | |
intents.message_content = True | |
intents.messages = True | |
intents.guilds = True | |
intents.guild_messages = True | |
# ์ถ๋ก API ํด๋ผ์ด์ธํธ ์ค์ | |
hf_client = InferenceClient("CohereForAI/c4ai-command-r-plus", token=os.getenv("HF_TOKEN")) | |
# ํน์ ์ฑ๋ ID | |
SPECIFIC_CHANNEL_ID = int(os.getenv("DISCORD_CHANNEL_ID")) | |
# ๋ํ ํ์คํ ๋ฆฌ๋ฅผ ์ ์ฅํ ์ ์ญ ๋ณ์ | |
conversation_history = [] | |
class MyClient(discord.Client): | |
def __init__(self, *args, **kwargs): | |
super().__init__(*args, **kwargs) | |
self.is_processing = False | |
async def on_ready(self): | |
logging.info(f'{self.user}๋ก ๋ก๊ทธ์ธ๋์์ต๋๋ค!') | |
subprocess.Popen(["python", "web.py"]) | |
logging.info("web.py ์๋ฒ๊ฐ ์์๋์์ต๋๋ค.") | |
async def on_message(self, message): | |
if message.author == self.user: | |
return | |
if not self.is_message_in_specific_channel(message): | |
return | |
if self.is_processing: | |
return | |
self.is_processing = True | |
try: | |
response = await handle_message(message) | |
await message.channel.send(response) | |
finally: | |
self.is_processing = False | |
def is_message_in_specific_channel(self, message): | |
return message.channel.id == SPECIFIC_CHANNEL_ID or ( | |
isinstance(message.channel, discord.Thread) and message.channel.parent_id == SPECIFIC_CHANNEL_ID | |
) | |
async def handle_message(message): | |
user_input = message.content | |
user_mention = message.author.mention | |
# ํฐ์ปค๋ฅผ ์ ๊ณตํ์ง ์์ ๊ฒฝ์ฐ | |
if not user_input.startswith("!t "): | |
ticker = await find_ticker(user_input) | |
if ticker: | |
return f"{user_mention}, ์ข ๋ชฉ๋ช ์ ์ฐพ์์ต๋๋ค: {ticker}. ํฐ์ปค ์ ๋ณด๋ฅผ ์ํ๋ฉด '!t {ticker}'๋ผ๊ณ ์ ๋ ฅํ์ธ์." | |
else: | |
return f"{user_mention}, ์ข ๋ชฉ๋ช ์ ์ฐพ์ ์ ์์ต๋๋ค. ์ฌ๋ฐ๋ฅธ ์ข ๋ชฉ๋ช ์ ์ ๋ ฅํ์ธ์." | |
# ํฐ์ปค๋ฅผ ์ ๊ณตํ ๊ฒฝ์ฐ | |
ticker = user_input[3:].strip().upper() | |
return await handle_ticker(ticker, user_mention) | |
async def handle_ticker(ticker, user_mention): | |
global conversation_history # ์ ์ญ ๋ณ์ ์ฌ์ฉ์ ๋ช ์ | |
conversation_history.append({"role": "user", "content": ticker}) | |
logging.debug(f'Conversation history updated: {conversation_history}') | |
company_info, charts, news_summary, prediction = await get_stock_info(ticker) | |
conversation_history.append({"role": "assistant", "content": prediction}) | |
if len(conversation_history) > 20: | |
conversation_history.pop(0) | |
return f""" | |
**ํ์ฌ ์ ๋ณด:** | |
ํ์ฌ ์ด๋ฆ: {company_info.get('longName', 'N/A')} | |
ํฐ์ปค: {ticker} | |
์ฐ์ : {company_info.get('industry', 'N/A')} | |
์นํฐ: {company_info.get('sector', 'N/A')} | |
์๊ฐ ์ด์ก: {company_info.get('marketCap', 'N/A')} | |
ํ์ฌ๊ฐ: {company_info.get('currentPrice', 'N/A')} | |
๋ฐ์ดํฐ ์ ๋ฐ์ดํธ: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} | |
**์ต๊ทผ 1์ผ ์ฐจํธ:** | |
{charts['1d']} | |
**์ต๊ทผ 1์ฃผ ์ฐจํธ:** | |
{charts['1w']} | |
**์ต๊ทผ 1๊ฐ์ ์ฐจํธ:** | |
{charts['1m']} | |
**์ต๊ทผ 1๋ ์ฐจํธ:** | |
{charts['1y']} | |
**์ต๊ทผ 10๋ ์ฐจํธ:** | |
{charts['10y']} | |
**์ต์ ๋ด์ค:** | |
{news_summary} | |
**ํฅํ 1์ฃผ์ผ๊ฐ ์์ธ ์์ธก:** | |
{prediction} | |
""" | |
async def find_ticker(query): | |
tickers = Ticker(query) | |
for ticker in tickers.symbols: | |
return ticker | |
return None | |
async def get_stock_info(ticker): | |
tickers = Ticker(ticker) | |
summary = tickers.summary_detail[ticker] | |
price = summary.get("previousClose", "N/A") | |
company_info = { | |
'longName': tickers.asset_profile[ticker].get('longName', 'N/A'), | |
'industry': tickers.asset_profile[ticker].get('industry', 'N/A'), | |
'sector': tickers.asset_profile[ticker].get('sector', 'N/A'), | |
'marketCap': summary.get('marketCap', 'N/A'), | |
'currentPrice': price, | |
} | |
charts = { | |
'1d': get_chart_summary(tickers.history(period="1d", interval="1d")), | |
'1w': get_chart_summary(tickers.history(period="5d", interval="1d")), | |
'1m': get_chart_summary(tickers.history(period="1mo", interval="1d")), | |
'1y': get_chart_summary(tickers.history(period="1y", interval="1d")), | |
'10y': get_chart_summary(tickers.history(period="10y", interval="1d")), | |
} | |
news_summary = get_news_summary(tickers.news()) | |
prediction = await predict_stock(ticker) | |
return company_info, charts, news_summary, prediction | |
def get_chart_summary(history): | |
if history.empty: | |
return "๋ฐ์ดํฐ ์์" | |
avg_price = history['close'].mean() | |
max_price = history['close'].max() | |
min_price = history['close'].min() | |
return f"ํ๊ท ๊ฐ: {avg_price:.2f}, ์ต๊ณ ๊ฐ: {max_price:.2f}, ์ต์ ๊ฐ: {min_price:.2f}" | |
def get_news_summary(news): | |
if not news: | |
return "๋ด์ค ์์ฝ์ ๊ฐ์ ธ์ค๋ ๋ฐ ์คํจํ์ต๋๋ค." | |
news_summary = "" | |
for article in news[:5]: | |
news_summary += f"- {article['title']}: {article['summary']}\n" | |
return news_summary.strip() | |
async def predict_stock(ticker): | |
messages = [{"role": "system", "content": f"์ฌ์ฉ์๊ฐ ํฐ์ปค '{ticker}'์ ๋ํด ์๊ณ ์ถ์ดํฉ๋๋ค."}] + conversation_history | |
logging.debug(f'๋ชจ๋ธ์ ๋ณด๋ผ ๋ฉ์์ง: {messages}') | |
loop = asyncio.get_event_loop() | |
response = await loop.run_in_executor(None, lambda: hf_client.chat_completion( | |
messages, max_tokens=1000, stream=True, temperature=0.7, top_p=0.85)) | |
full_response = [] | |
for part in response: | |
if part.choices and part.choices[0].delta and part.choices[0].delta.content: | |
full_response.append(part.choices[0].delta.content) | |
return ''.join(full_response).strip() | |
if __name__ == "__main__": | |
discord_token = os.getenv('DISCORD_TOKEN') | |
discord_client = MyClient(intents=intents) | |
discord_client.run(discord_token) | |