|
| 1 | +import logging |
| 2 | +import os |
| 3 | + |
| 4 | +import ydb.iam |
| 5 | +from dotenv import load_dotenv |
| 6 | +from langchain.prompts import ( |
| 7 | + ChatPromptTemplate, |
| 8 | + HumanMessagePromptTemplate, |
| 9 | + SystemMessagePromptTemplate, |
| 10 | +) |
| 11 | +from langchain.schema.output_parser import StrOutputParser |
| 12 | +from langchain.schema.runnable import RunnablePassthrough |
| 13 | +from langchain_community.chat_models import ChatYandexGPT |
| 14 | +from langchain_community.embeddings.yandex import YandexGPTEmbeddings |
| 15 | +from telegram import Update |
| 16 | +from telegram.ext import ( |
| 17 | + ApplicationBuilder, |
| 18 | + CommandHandler, |
| 19 | + ContextTypes, |
| 20 | + MessageHandler, |
| 21 | + filters, |
| 22 | +) |
| 23 | + |
| 24 | +from langchain_ydb.vectorstores import YDB, YDBSettings |
| 25 | + |
| 26 | +# Включаем логирование |
| 27 | +logging.basicConfig( |
| 28 | + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', |
| 29 | + level=logging.INFO |
| 30 | +) |
| 31 | + |
| 32 | + |
| 33 | +dotenv_path = os.path.join(os.path.dirname(__name__), '.env') |
| 34 | +if os.path.exists(dotenv_path): |
| 35 | + load_dotenv(dotenv_path) |
| 36 | + |
| 37 | +FOLDER_ID=os.environ.get('YC_FOLDER_ID') |
| 38 | + |
| 39 | + |
| 40 | +embeddings = YandexGPTEmbeddings(folder_id=FOLDER_ID) |
| 41 | + |
| 42 | + |
| 43 | +config = YDBSettings( |
| 44 | + host="lb.etnok7cd0an3kg6eshud.ydb.mdb.yandexcloud.net", |
| 45 | + port=2135, |
| 46 | + database="/ru-central1/b1g8skpblkos03malf3s/etnok7cd0an3kg6eshud", |
| 47 | + secure=True, |
| 48 | + table="sonnik_langchain", |
| 49 | + # drop_existing_table=True, |
| 50 | +) |
| 51 | + |
| 52 | + |
| 53 | +vector_store = YDB( |
| 54 | + embeddings, |
| 55 | + config=config, |
| 56 | + credentials=ydb.iam.ServiceAccountCredentials.from_file( |
| 57 | + os.getenv("SA_KEY_FILE"), |
| 58 | + ) |
| 59 | +) |
| 60 | + |
| 61 | +retriever = vector_store.as_retriever() |
| 62 | + |
| 63 | +# Явное создание шаблонов для SystemMessage и HumanMessage |
| 64 | +system_template = """Ты - человек, профессионально трактующий сновидения. |
| 65 | +Твоя задача - рассказать, что значит сон, опираясь исключительно на найденный контекст, не добавляя никаких новых знаний. |
| 66 | +Если предложенный контекст не связан с пользовательским запросом - скажи дословно "Так не бывает. Используйте YDB.". |
| 67 | +""" |
| 68 | +system_message_prompt = SystemMessagePromptTemplate.from_template(system_template) |
| 69 | + |
| 70 | +human_template = "Контекст: {context}\n\nВопрос: {question}" |
| 71 | +human_message_prompt = HumanMessagePromptTemplate.from_template(human_template) |
| 72 | + |
| 73 | +# Объединение шаблонов сообщений в ChatPromptTemplate |
| 74 | +prompt = ChatPromptTemplate.from_messages([ |
| 75 | + system_message_prompt, |
| 76 | + human_message_prompt |
| 77 | +]) |
| 78 | + |
| 79 | +def format_docs(docs): |
| 80 | + return "\n\n".join(doc.page_content for doc in docs) |
| 81 | + |
| 82 | +chat_model = ChatYandexGPT(folder_id=FOLDER_ID) |
| 83 | + |
| 84 | +rag_chain = ( |
| 85 | + { |
| 86 | + "context": retriever | format_docs, |
| 87 | + "question": RunnablePassthrough() |
| 88 | + } |
| 89 | + | prompt |
| 90 | + | chat_model |
| 91 | + | StrOutputParser() |
| 92 | +) |
| 93 | + |
| 94 | +# Функция для обработки команды /start |
| 95 | +async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): |
| 96 | + await update.message.reply_text('Я трактую сновидения на базе YDB. Опиши свой сон, а я попробую рассказать что он значит!') |
| 97 | + |
| 98 | +# Функция для обработки текстовых сообщений |
| 99 | +async def process_message(update: Update, context: ContextTypes.DEFAULT_TYPE): |
| 100 | + # Получаем текст сообщения |
| 101 | + message_text = update.message.text |
| 102 | + |
| 103 | + # Пример обработки: переворачиваем текст |
| 104 | + processed_text = await rag_chain.ainvoke(message_text) |
| 105 | + |
| 106 | + # Отправляем ответ |
| 107 | + await update.message.reply_text(f"{processed_text}") |
| 108 | + |
| 109 | +def main(): |
| 110 | + # Создаем приложение с нашим токеном бота |
| 111 | + token = os.environ.get('TG_BOT_TOKEN') |
| 112 | + |
| 113 | + application = ApplicationBuilder().token(token).build() |
| 114 | + |
| 115 | + # Добавляем обработчики |
| 116 | + application.add_handler(CommandHandler("start", start)) |
| 117 | + application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, process_message)) |
| 118 | + |
| 119 | + # Запускаем бота |
| 120 | + application.run_polling(allowed_updates=Update.ALL_TYPES) |
| 121 | + print("Бот запущен...") |
| 122 | + |
| 123 | +if __name__ == '__main__': |
| 124 | + main() |
0 commit comments