nahj_rag/nahj_engine_general_runner.py

192 lines
6.2 KiB
Python

"""
این سرویس، هسته اصلی نهج البلاغه را اجرا می کند
"""
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