""" این سرویس، هسته اصلی نهج البلاغه را اجرا می کند """ import json from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel import requests import logging import uvicorn import random import time import nahj_engine as nahj_chat import data_model as dm from typing import Optional, Dict # =========================== # پیکربندی اولیه # =========================== TOKEN = "602738113:OcVhjcsXqvE6D9FUytdoMZ096DPKYIUwnrk" API_URL = f"https://tapi.bale.ai/bot{TOKEN}/" # راه‌اندازی لاگر logging.basicConfig( filename="./bale_bot/bot.log", level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s" ) # =========================== # define import model class # =========================== class Message(BaseModel): user_query: str class Update(BaseModel): message: Message | None = None async def get_latest_req_id(): latest_request = dm.get_last_request() latest_req_id = latest_request['update_id'] if not latest_req_id: latest_req_id = 0 return latest_req_id + 1 async def save_entery(update_item): is_active = True answer = '' message = update_item['message'] fromm = message['from'] chat = message['chat'] username, first_name, last_name = '','','' if 'username' in fromm: username = fromm['username'] if 'first_name' in fromm: first_name = fromm['first_name'] if 'last_name' in fromm: last_name = fromm['last_name'] try: dm.insert_request(update_item['update_id'],username,message['text'], answer, message['message_id'],fromm['id'],fromm['is_bot'],message['date'],chat['id'],chat['type'],first_name,last_name, is_active) except: return update_item['update_id'] return update_item['update_id'] async def update_request(update_id, answer): dm.update_request(update_id= update_id, answer= answer) async def split_text_into_chunks(text, max_length=4000): """ تقسیم یک متن به چانک‌های حداکثر max_length کاراکتری، بدون خراب کردن معنا با رعایت انتهای جمله‌ها. :param text: متن ورودی :param max_length: حداکثر طول هر چانک (پیش‌فرض 4000) :return: لیستی از چانک‌های متن """ chunks = [] # لیستی برای ذخیره چانک‌ها start = 0 # شروع متن برای هر چانک while start < len(text): # اگر متن باقی‌مانده کوتاه‌تر از max_length باشد، کل آن را اضافه کنید if len(text) - start <= max_length: chunks.append(text[start:]) break # پیدا کردن نقطه پایانی چانک (حداکثر تا max_length کاراکتر جلو بروید) end = start + max_length # اگر در وسط یک جمله هستیم، به عقب برگردید تا انتهای جمله پیدا شود while end > start and text[end - 1] not in '.!?': end -= 1 # اگر هیچ انتهای جمله پیدا نشد، متن را تا max_length ببرید if end == start: end = start + max_length # اضافه کردن چانک به لیست chunks.append(text[start:end]) # شروع چانک بعدی start = end return chunks async def save_chat_data(query, answer, first_name, username): chat_data = f'''username: {username}\nfirstname: {first_name}\nquery: {query}\nanswer:{answer}\n+ + + + + + + + + + + + + + + + + + + + \n+ + + + + + + + + + + + + + + + + + + + \n\n''' # # should write in DATABASE with open('./bale_bot/chat-data.txt', 'a+', encoding='utf-8') as file: file.write(chat_data) # =========================== # ساخت اپلیکیشن FastAPI # =========================== app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=["*"], # یا دامنه فرانت‌اند allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.post("/chat") async def chat(request: Message): """ دریافت مستقیم آبجکت ورودی به صورت JSON """ # دریافت بدنه درخواست body = dict(request) user_query = body.get('user_query') # دسترسی به فیلدها # user_input = body.get("message") # metadata = body.get("metadata", {}) # update_id = await save_entery(item) update_id = random.randint(1, 10) answer = nahj_chat.bale_chat(user_query) if not answer: answer['output'] = 'خطا در تولید پاسخ!' answer['status'] = 'Failed' answer['similarity_result'] = [] answer['reference_ids'] = [] if answer: try: await update_request(update_id = update_id, answer = answer['output']) except: pass print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') retrived_sections_list = answer['similarity_result'] print(type(retrived_sections_list)) print(retrived_sections_list) print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') # برگرداندن آبجکت خروجی (خودکار به JSON تبدیل می‌شود) return answer print(f'%%%%%%%%%%%%%%%%%%%%%%%%%%%%') print(f'!!! NAHJ-RUNNER IS READY !!!') print(f'%%%%%%%%%%%%%%%%%%%%%%%%%%%%') # =========================== # (local execution) # =========================== # if __name__ == "__main__": # import asyncio # result = asyncio.run(chat()) if __name__ == "__main__": pass # uvicorn.run(app, host="127.0.0.1", port=8010) # uvicorn.run( # "nahj_engine_general_runner:app", # host="0.0.0.0", # port=8010, # reload=True, # فعال بودن reload برای دیباگ مفید است # log_level="debug" # ) # uvicorn nahj_engine_general_runner:app --reload --host 0.0.0.0 --port 8010 # uvicorn main:app --reload --host 0.0.0.0 --port 8000 >> runs llm for pajoohesh