텔레그램과 랭체인을 연결하여 문서와 링크 축적하기

그동안 엄선해 놓은 텔레그램 채널 구독을 통해 들어오는 산업 트렌드와 기업 정보들을 한군데 모아서 지식창고화 하는 프로젝트를 진행하고자 프로젝트를 시작했습니다. 😀

RAG를 활용해 보고자 했지만, 이번주는 파이썬으로 텔레그램을 갖고 놀 수 있는 기반을 갖추는 데에 만족해야겠네요 😮‍💨

1. 텔레그램 개발 환경 갖추기

텔레그램 Bot API 및 텔레그램 Core API 를 활용한 채널 및 채팅 데이터 포워딩 방법을 모두 알아본 결과, 봇으로는 한계가 명확하고, 결국 Core API 를 활용해야 함을 깨달았습니다. ㅎㅎ 비교적 빠른 판단.

꽁으로 API 를 활용해 보는 짧은 과정 이후, 굳이 그럴 필요 없이 잘 만들어져 있는 Telethon 을 활용하는게 가장 효율적이라는 결론에 도달, 빠르게 Telethon 으로, 가장 원하고 원하던, 구독채널 데이터를 한곳으로 보내는 데까지 해보기로 했습니다.

결론은, 텔레그램으로 뭘 해보려면 이런저런 삽질 하지 말고 Telethon 을 활용하는게 답인거 같네요.

  1. Telegram Bot API 등록, Telegram API 및 APP 생성하여 App_id 와 Api_hash 키 얻기

  2. Telethon 등록하기
    - 아래 Telethon 사이트를 참조해서 설치하고 Telethon 세션 등록하기
    - Telethon 알아보러 가기
    - 사이트에 들어가서, 아래 첫페이지에서 Installation! → 이부분만 따라하면 그리 어렵지 않더군요.

2. Telethon을 활용하여 구독채널 메세지 한 곳으로 가져오기

백문이 불여일견! 예제 몇개 보고 바로 내가 원하는 구독 채널 메세지를 몽땅 가져와서 내가 만든 텔레그램봇한테 싹 다 모아서 보내는 코드를 작성해서 실행해 봅니다. 뭐 있어? 해보는거지. 🤠

자세한건 아래 코드에 인라인 설명으로…

.env

# 텔레그램 Bot 토큰
TELEGRAM_BOT_TOKEN="7095256272:AAF7eNVPwiJf4do2QShzIRvcTzUXjfu6Wzs"
# 텔레그램 App ID 및 Api hash
TELEGRAM_APP_ID="883836"
TELEGRAM_API_HASH="b94a10597a97ede23136a7e362308702"
telegram_test.py

import os
from dotenv import load_dotenv

from telethon import TelegramClient, events, utils
from telethon.tl import types, functions
from telethon.tl.types import PeerChannel
from telethon.tl.types import Message

load_dotenv()


client = TelegramClient('ohmyelf', os.environ.get("TELEGRAM_APP_ID"), os.environ.get("TELEGRAM_API_HASH"))

# 메세지를 받아오고자 하는 채널들의 채널아이디 목록
channel_ids = {'EvAtZchuno','hantudong','siglab'}

# 내가 메세지를 모으고자 하는 내 봇의 chat id 지정
# chat id를 알아내는 방법은, 아래와 같이 모든 대화목록에서 name 과 id 를 매칭해서 프린트 해보고 찾아내는 방법을 활용했습니다. 더 나은 방법은 차차 알아봐야겠쥬?
# async for dialog in client.iter_dialogs():
#      print(dialog.name, 'has ID', dialog.id)
bot_chat_id = 2197248047

# annotation 을 통해 원하는 특정 채널들의 신규 메세지 이벤트 받아옵니다. 참 쉽쥬?
# chats=channel_ids -> 요걸로 원하는 채널들의 메세지 이벤트만 골라서 받아 수 있습니다.
@client.on(events.NewMessage(chats=channel_ids))
async def my_event_handler(event):
    print("#####")
    print(event.raw_text)
    print("#####")
    print(event.message.forwards)
    print("#####")
    print(event.message.peer_id)
    print("#####")
    print(event.message)

    # 여기에서 들어오는 모든 메세지를 bot_chat_id 채널로 몽땅 포워딩하면 싹 다 모아지겠네요~ 
    # Telethon은, 쌩 API 가지고 환경잡고 테스트 해봤던 것에 비해서는 참 간단하게 잘 만들어진 라이브러리 같아요. 다른 분들은 고민고민하지 마시고 바로 Telethon으로!!! 
    await client.forward_messages(entity=bot_chat_id, messages=event.message, from_peer=event.message.peer_id)

def main():

    client.start()
    client.run_until_disconnected()

main()

요렇게 하면 아래와 같이 ElfDataLab 이라고 하는 제가 만든 Bot 채널로 제가 선택한 채널들의 모든 메세지가 모이는 것을 확인할 수 있겠숨다~
항상 해놓고 는 걸 보면 참 쉽죠이? 실상은 하루 꼬박 사용한 결과입니다~

3. 내 봇으로 구독채널 메세지를 랭체인으로 요약해서 가져오기

일단, 아주 간단하게 랭체인을 활용해서 텍스트 원문을 요약하거나, 링크가 함께 있는 메세지인 경우에는 링크 타고 들어가서 원문을 요약해서 가져오게 해 보겠습니다.

한단계씩 앞으로 가야 하니, 일단 간단하게 여기부터…

import os
from dotenv import load_dotenv

from telethon import TelegramClient, events, utils
from telethon.tl import types, functions
from telethon.tl.types import PeerChannel
from telethon.tl.types import Message

load_dotenv()


# 메시지를 받았을 때, GPT-3 API를 활용해 답변을 작성하는 함수를 정의합니다. 
# llm = ChatOpenAI(model_name="gpt-4o")
llm = ChatOpenAI()
output = StrOutputParser()

#######################################################
# 메세지 요약하기
def generate_response(message):
    
    # 텍스트로부터 URL을 추출한다, 
    urls = re.findall("(?P<url>https?://[^\s]+)", message)

    #   URL 있을 경우 : 해당 url 콘텐츠를 읽어 들여서 요약을 수행하게 하고,
    #   URL 없을 경우 : 메세지를 그대로 읽어 들여서 요약을 수행하게 한다.
    if len(urls) > 0:
        prompt = PromptTemplate.from_template(
            """
            You are my asset manager and analyst with over 20 years of experience. 
            Please read the contents and Write the key points of the contents in 3000 characters or less and if there is links include the links to the bottom.
            if possible, with mark-down and just write in Korean.
            contents : {document}
            links : {links}
            """
            )
        
        url_loader = UnstructuredURLLoader(urls=urls)
        message = url_loader.load()
        chain =  prompt | llm | output
        
        answer = '# 요약 : \n' + chain.invoke({"document":message, "links":urls}) + '\n'
    else :
        prompt = PromptTemplate.from_template(
            """
            You are my asset manager and analyst with over 20 years of experience. 
            Please read the contents and Write the key points of the contents in 3000 characters or less
            if possible, with mark-down and just write in Korean.
            contents : {document}
            """
            )
        chain =  prompt | llm | output
        answer = '# 요약 : \n' + chain.invoke({"document":message}) + '\n'

    return answer
#######################################################

client = TelegramClient('ohmyelf', os.environ.get("TELEGRAM_APP_ID"), os.environ.get("TELEGRAM_API_HASH"))

# 메세지를 받아오고자 하는 채널들의 채널아이디 목록
channel_ids = {'EvAtZchuno','hantudong','siglab'}

# 내가 메세지를 모으고자 하는 내 봇의 chat id 지정
# chat id를 알아내는 방법은, 아래와 같이 모든 대화목록에서 name 과 id 를 매칭해서 프린트 해보고 찾아내는 방법을 활용했습니다. 더 나은 방법은 차차 알아봐야겠쥬?
# async for dialog in client.iter_dialogs():
#      print(dialog.name, 'has ID', dialog.id)
bot_chat_id = 2197248047

# annotation 을 통해 원하는 특정 채널들의 신규 메세지 이벤트 받아옵니다. 참 쉽쥬?
# chats=channel_ids -> 요걸로 원하는 채널들의 메세지 이벤트만 골라서 받아 수 있습니다.
@client.on(events.NewMessage(chats=channel_ids))
async def my_event_handler(event):

    # 여기에서 들어오는 모든 메세지를 bot_chat_id 채널로 몽땅 포워딩하면 싹 다 모아지겠네요~ 
    # Telethon은, 쌩 API 가지고 환경잡고 테스트 해봤던 것에 비해서는 참 간단하게 잘 만들어진 라이브러리 같아요. 다른 분들은 고민고민하지 마시고 바로 Telethon으로!!! 
    # await client.forward_messages(entity=bot_chat_id, messages=event.message, from_peer=event.message.peer_id)

    # 포워딩 대신에 요약결과를 넘겨 보겠습니다.
    answer = generate_response(event.raw_text)
    
    await client.send_message(entity=2197248047, message=answer)
def main():

    client.start()
    client.run_until_disconnected()

main()

요렇게 하면 아래와 같이 ElfDataLab 이라고 하는 제가 만든 Bot 채널로 요약된 결과물이 새로운 메세지로 만들어져서 기록되는걸 확인할 수 있네요~ 🤭

다음 단계는 ?

일단, 다음단계는, 아래와 같은 순서로 진행해 볼까 합니다.

  1. 품질 개선 : 링크원문 데이터를 좀 더 잘 가져오는 방법을 찾고, 프롬프트를 좀 더 정교하게 해서 요약 품질을 높이는 것입니다.

  2. 데이터화하여 저장하기
    - 가져온 메세지를 원문, 요약, 링크, 링크 내 원문 등 데이터로 분리하여 저장하기

  3. 필터링 기능 구현하기
    - 단순 키워드 등을 활용하여 positive 필터, negative 필터 기능 적용하기
    - 프롬프트를 활용하여 내가 원하는 메세지만 고르거나(positive) 제외하여(negative) 필터링하기

  4. 중복 제거하기
    - 과거 받았던 메세지와 유사도를 분석하여 80%이상이면 중복으로 보고 제거하기
    단, 동일 날짜에 중복시 중복 카운트를 저장하여 중요한 내용으로 보고, 가중치로 활용하기

  5. 메세지 학습시키기
    - 내가 채널로부터 전달하는 텍스트 데이터들을 모두 학습하면서 점점 더 내 정보 분석 비서가 되어갈 수 있도록 훈련시키기
    - 로컬 LLM 을 어떻게 하면 시간이 갈수록 나와 비슷한 정보를 계속 학습해 가는 AI 비서로 만들 수 있을까?


#11기 랭체인

11
2개의 답글

👉 이 게시글도 읽어보세요