192 lines
6.2 KiB
Python
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 |