#!/usr/bin/env python """ 独立运行的LLM后台计费程序。 从 sage.py 的 llmage 模块中提取,避免多进程模式下重复运行。 """ import os import sys import asyncio import signal # 切换到 Sage 工作目录 os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'py3', 'lib', 'python3.10', 'site-packages')) sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'pkgs')) from appPublic.folderUtils import ProgramPath from appPublic.jsonConfig import getConfig from sqlor.dbpools import DBPools from appPublic.log import MyLogger, debug, exception, info # 初始化配置 p = ProgramPath() config = getConfig(NS={'workdir': os.getcwd(), 'ProgramPath': p}) DBPools(config.databases) # 导入 llmage 的计费函数 from llmage.accounting import ( get_accounting_llmusages, llm_accounting, llm_accoung_failed ) async def backend_accounting(): """LLM 使用计费循环""" info('backend accounting started ...') while True: try: lus = await get_accounting_llmusages() except Exception as e: exception(f'{e}') lus = [] debug(f'{len(lus)=} need to accounting........') for lu in lus: try: debug(f'backend_accounting(): {lu.id=} handleing...') await llm_accounting(lu) except Exception as e: exception(f'{e}, {lu.id=}') await llm_accoung_failed(lu.id) await asyncio.sleep(10) def main(): logger = MyLogger('backend_accounting', levelname='info', logfile=os.path.join(os.getcwd(), 'logs', 'backend_accounting.log')) info(f'Backend accounting process started (PID: {os.getpid()})') loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) def handle_signal(signum, frame): info(f'Received signal {signum}, shutting down...') for task in asyncio.all_tasks(loop): task.cancel() loop.stop() signal.signal(signal.SIGTERM, handle_signal) signal.signal(signal.SIGINT, handle_signal) try: loop.run_until_complete(backend_accounting()) except asyncio.CancelledError: pass finally: loop.close() info('Backend accounting process stopped.') if __name__ == '__main__': main()