Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. from datetime import datetime
  2. from decimal import Decimal
  3. import pytz
  4. import sqlalchemy as sa
  5. from flask import jsonify
  6. from flask_login import current_user
  7. from flask_restx import Resource, fields, reqparse
  8. from controllers.console import api, console_ns
  9. from controllers.console.app.wraps import get_app_model
  10. from controllers.console.wraps import account_initialization_required, setup_required
  11. from core.app.entities.app_invoke_entities import InvokeFrom
  12. from extensions.ext_database import db
  13. from libs.helper import DatetimeString
  14. from libs.login import login_required
  15. from models import AppMode, Message
  16. @console_ns.route("/apps/<uuid:app_id>/statistics/daily-messages")
  17. class DailyMessageStatistic(Resource):
  18. @api.doc("get_daily_message_statistics")
  19. @api.doc(description="Get daily message statistics for an application")
  20. @api.doc(params={"app_id": "Application ID"})
  21. @api.expect(
  22. api.parser()
  23. .add_argument("start", type=str, location="args", help="Start date (YYYY-MM-DD HH:MM)")
  24. .add_argument("end", type=str, location="args", help="End date (YYYY-MM-DD HH:MM)")
  25. )
  26. @api.response(
  27. 200,
  28. "Daily message statistics retrieved successfully",
  29. fields.List(fields.Raw(description="Daily message count data")),
  30. )
  31. @get_app_model
  32. @setup_required
  33. @login_required
  34. @account_initialization_required
  35. def get(self, app_model):
  36. account = current_user
  37. parser = reqparse.RequestParser()
  38. parser.add_argument("start", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  39. parser.add_argument("end", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  40. args = parser.parse_args()
  41. sql_query = """SELECT
  42. DATE(DATE_TRUNC('day', created_at AT TIME ZONE 'UTC' AT TIME ZONE :tz )) AS date,
  43. COUNT(*) AS message_count
  44. FROM
  45. messages
  46. WHERE
  47. app_id = :app_id
  48. AND invoke_from != :invoke_from"""
  49. arg_dict = {"tz": account.timezone, "app_id": app_model.id, "invoke_from": InvokeFrom.DEBUGGER.value}
  50. timezone = pytz.timezone(account.timezone)
  51. utc_timezone = pytz.utc
  52. if args["start"]:
  53. start_datetime = datetime.strptime(args["start"], "%Y-%m-%d %H:%M")
  54. start_datetime = start_datetime.replace(second=0)
  55. start_datetime_timezone = timezone.localize(start_datetime)
  56. start_datetime_utc = start_datetime_timezone.astimezone(utc_timezone)
  57. sql_query += " AND created_at >= :start"
  58. arg_dict["start"] = start_datetime_utc
  59. if args["end"]:
  60. end_datetime = datetime.strptime(args["end"], "%Y-%m-%d %H:%M")
  61. end_datetime = end_datetime.replace(second=0)
  62. end_datetime_timezone = timezone.localize(end_datetime)
  63. end_datetime_utc = end_datetime_timezone.astimezone(utc_timezone)
  64. sql_query += " AND created_at < :end"
  65. arg_dict["end"] = end_datetime_utc
  66. sql_query += " GROUP BY date ORDER BY date"
  67. response_data = []
  68. with db.engine.begin() as conn:
  69. rs = conn.execute(sa.text(sql_query), arg_dict)
  70. for i in rs:
  71. response_data.append({"date": str(i.date), "message_count": i.message_count})
  72. return jsonify({"data": response_data})
  73. @console_ns.route("/apps/<uuid:app_id>/statistics/daily-conversations")
  74. class DailyConversationStatistic(Resource):
  75. @api.doc("get_daily_conversation_statistics")
  76. @api.doc(description="Get daily conversation statistics for an application")
  77. @api.doc(params={"app_id": "Application ID"})
  78. @api.expect(
  79. api.parser()
  80. .add_argument("start", type=str, location="args", help="Start date (YYYY-MM-DD HH:MM)")
  81. .add_argument("end", type=str, location="args", help="End date (YYYY-MM-DD HH:MM)")
  82. )
  83. @api.response(
  84. 200,
  85. "Daily conversation statistics retrieved successfully",
  86. fields.List(fields.Raw(description="Daily conversation count data")),
  87. )
  88. @get_app_model
  89. @setup_required
  90. @login_required
  91. @account_initialization_required
  92. def get(self, app_model):
  93. account = current_user
  94. parser = reqparse.RequestParser()
  95. parser.add_argument("start", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  96. parser.add_argument("end", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  97. args = parser.parse_args()
  98. timezone = pytz.timezone(account.timezone)
  99. utc_timezone = pytz.utc
  100. stmt = (
  101. sa.select(
  102. sa.func.date(
  103. sa.func.date_trunc("day", sa.text("created_at AT TIME ZONE 'UTC' AT TIME ZONE :tz"))
  104. ).label("date"),
  105. sa.func.count(sa.distinct(Message.conversation_id)).label("conversation_count"),
  106. )
  107. .select_from(Message)
  108. .where(Message.app_id == app_model.id, Message.invoke_from != InvokeFrom.DEBUGGER.value)
  109. )
  110. if args["start"]:
  111. start_datetime = datetime.strptime(args["start"], "%Y-%m-%d %H:%M")
  112. start_datetime = start_datetime.replace(second=0)
  113. start_datetime_timezone = timezone.localize(start_datetime)
  114. start_datetime_utc = start_datetime_timezone.astimezone(utc_timezone)
  115. stmt = stmt.where(Message.created_at >= start_datetime_utc)
  116. if args["end"]:
  117. end_datetime = datetime.strptime(args["end"], "%Y-%m-%d %H:%M")
  118. end_datetime = end_datetime.replace(second=0)
  119. end_datetime_timezone = timezone.localize(end_datetime)
  120. end_datetime_utc = end_datetime_timezone.astimezone(utc_timezone)
  121. stmt = stmt.where(Message.created_at < end_datetime_utc)
  122. stmt = stmt.group_by("date").order_by("date")
  123. response_data = []
  124. with db.engine.begin() as conn:
  125. rs = conn.execute(stmt, {"tz": account.timezone})
  126. for row in rs:
  127. response_data.append({"date": str(row.date), "conversation_count": row.conversation_count})
  128. return jsonify({"data": response_data})
  129. @console_ns.route("/apps/<uuid:app_id>/statistics/daily-end-users")
  130. class DailyTerminalsStatistic(Resource):
  131. @api.doc("get_daily_terminals_statistics")
  132. @api.doc(description="Get daily terminal/end-user statistics for an application")
  133. @api.doc(params={"app_id": "Application ID"})
  134. @api.expect(
  135. api.parser()
  136. .add_argument("start", type=str, location="args", help="Start date (YYYY-MM-DD HH:MM)")
  137. .add_argument("end", type=str, location="args", help="End date (YYYY-MM-DD HH:MM)")
  138. )
  139. @api.response(
  140. 200,
  141. "Daily terminal statistics retrieved successfully",
  142. fields.List(fields.Raw(description="Daily terminal count data")),
  143. )
  144. @get_app_model
  145. @setup_required
  146. @login_required
  147. @account_initialization_required
  148. def get(self, app_model):
  149. account = current_user
  150. parser = reqparse.RequestParser()
  151. parser.add_argument("start", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  152. parser.add_argument("end", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  153. args = parser.parse_args()
  154. sql_query = """SELECT
  155. DATE(DATE_TRUNC('day', created_at AT TIME ZONE 'UTC' AT TIME ZONE :tz )) AS date,
  156. COUNT(DISTINCT messages.from_end_user_id) AS terminal_count
  157. FROM
  158. messages
  159. WHERE
  160. app_id = :app_id
  161. AND invoke_from != :invoke_from"""
  162. arg_dict = {"tz": account.timezone, "app_id": app_model.id, "invoke_from": InvokeFrom.DEBUGGER.value}
  163. timezone = pytz.timezone(account.timezone)
  164. utc_timezone = pytz.utc
  165. if args["start"]:
  166. start_datetime = datetime.strptime(args["start"], "%Y-%m-%d %H:%M")
  167. start_datetime = start_datetime.replace(second=0)
  168. start_datetime_timezone = timezone.localize(start_datetime)
  169. start_datetime_utc = start_datetime_timezone.astimezone(utc_timezone)
  170. sql_query += " AND created_at >= :start"
  171. arg_dict["start"] = start_datetime_utc
  172. if args["end"]:
  173. end_datetime = datetime.strptime(args["end"], "%Y-%m-%d %H:%M")
  174. end_datetime = end_datetime.replace(second=0)
  175. end_datetime_timezone = timezone.localize(end_datetime)
  176. end_datetime_utc = end_datetime_timezone.astimezone(utc_timezone)
  177. sql_query += " AND created_at < :end"
  178. arg_dict["end"] = end_datetime_utc
  179. sql_query += " GROUP BY date ORDER BY date"
  180. response_data = []
  181. with db.engine.begin() as conn:
  182. rs = conn.execute(sa.text(sql_query), arg_dict)
  183. for i in rs:
  184. response_data.append({"date": str(i.date), "terminal_count": i.terminal_count})
  185. return jsonify({"data": response_data})
  186. @console_ns.route("/apps/<uuid:app_id>/statistics/token-costs")
  187. class DailyTokenCostStatistic(Resource):
  188. @api.doc("get_daily_token_cost_statistics")
  189. @api.doc(description="Get daily token cost statistics for an application")
  190. @api.doc(params={"app_id": "Application ID"})
  191. @api.expect(
  192. api.parser()
  193. .add_argument("start", type=str, location="args", help="Start date (YYYY-MM-DD HH:MM)")
  194. .add_argument("end", type=str, location="args", help="End date (YYYY-MM-DD HH:MM)")
  195. )
  196. @api.response(
  197. 200,
  198. "Daily token cost statistics retrieved successfully",
  199. fields.List(fields.Raw(description="Daily token cost data")),
  200. )
  201. @get_app_model
  202. @setup_required
  203. @login_required
  204. @account_initialization_required
  205. def get(self, app_model):
  206. account = current_user
  207. parser = reqparse.RequestParser()
  208. parser.add_argument("start", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  209. parser.add_argument("end", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  210. args = parser.parse_args()
  211. sql_query = """SELECT
  212. DATE(DATE_TRUNC('day', created_at AT TIME ZONE 'UTC' AT TIME ZONE :tz )) AS date,
  213. (SUM(messages.message_tokens) + SUM(messages.answer_tokens)) AS token_count,
  214. SUM(total_price) AS total_price
  215. FROM
  216. messages
  217. WHERE
  218. app_id = :app_id
  219. AND invoke_from != :invoke_from"""
  220. arg_dict = {"tz": account.timezone, "app_id": app_model.id, "invoke_from": InvokeFrom.DEBUGGER.value}
  221. timezone = pytz.timezone(account.timezone)
  222. utc_timezone = pytz.utc
  223. if args["start"]:
  224. start_datetime = datetime.strptime(args["start"], "%Y-%m-%d %H:%M")
  225. start_datetime = start_datetime.replace(second=0)
  226. start_datetime_timezone = timezone.localize(start_datetime)
  227. start_datetime_utc = start_datetime_timezone.astimezone(utc_timezone)
  228. sql_query += " AND created_at >= :start"
  229. arg_dict["start"] = start_datetime_utc
  230. if args["end"]:
  231. end_datetime = datetime.strptime(args["end"], "%Y-%m-%d %H:%M")
  232. end_datetime = end_datetime.replace(second=0)
  233. end_datetime_timezone = timezone.localize(end_datetime)
  234. end_datetime_utc = end_datetime_timezone.astimezone(utc_timezone)
  235. sql_query += " AND created_at < :end"
  236. arg_dict["end"] = end_datetime_utc
  237. sql_query += " GROUP BY date ORDER BY date"
  238. response_data = []
  239. with db.engine.begin() as conn:
  240. rs = conn.execute(sa.text(sql_query), arg_dict)
  241. for i in rs:
  242. response_data.append(
  243. {"date": str(i.date), "token_count": i.token_count, "total_price": i.total_price, "currency": "USD"}
  244. )
  245. return jsonify({"data": response_data})
  246. @console_ns.route("/apps/<uuid:app_id>/statistics/average-session-interactions")
  247. class AverageSessionInteractionStatistic(Resource):
  248. @api.doc("get_average_session_interaction_statistics")
  249. @api.doc(description="Get average session interaction statistics for an application")
  250. @api.doc(params={"app_id": "Application ID"})
  251. @api.expect(
  252. api.parser()
  253. .add_argument("start", type=str, location="args", help="Start date (YYYY-MM-DD HH:MM)")
  254. .add_argument("end", type=str, location="args", help="End date (YYYY-MM-DD HH:MM)")
  255. )
  256. @api.response(
  257. 200,
  258. "Average session interaction statistics retrieved successfully",
  259. fields.List(fields.Raw(description="Average session interaction data")),
  260. )
  261. @setup_required
  262. @login_required
  263. @account_initialization_required
  264. @get_app_model(mode=[AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT])
  265. def get(self, app_model):
  266. account = current_user
  267. parser = reqparse.RequestParser()
  268. parser.add_argument("start", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  269. parser.add_argument("end", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  270. args = parser.parse_args()
  271. sql_query = """SELECT
  272. DATE(DATE_TRUNC('day', c.created_at AT TIME ZONE 'UTC' AT TIME ZONE :tz )) AS date,
  273. AVG(subquery.message_count) AS interactions
  274. FROM
  275. (
  276. SELECT
  277. m.conversation_id,
  278. COUNT(m.id) AS message_count
  279. FROM
  280. conversations c
  281. JOIN
  282. messages m
  283. ON c.id = m.conversation_id
  284. WHERE
  285. c.app_id = :app_id
  286. AND m.invoke_from != :invoke_from"""
  287. arg_dict = {"tz": account.timezone, "app_id": app_model.id, "invoke_from": InvokeFrom.DEBUGGER.value}
  288. timezone = pytz.timezone(account.timezone)
  289. utc_timezone = pytz.utc
  290. if args["start"]:
  291. start_datetime = datetime.strptime(args["start"], "%Y-%m-%d %H:%M")
  292. start_datetime = start_datetime.replace(second=0)
  293. start_datetime_timezone = timezone.localize(start_datetime)
  294. start_datetime_utc = start_datetime_timezone.astimezone(utc_timezone)
  295. sql_query += " AND c.created_at >= :start"
  296. arg_dict["start"] = start_datetime_utc
  297. if args["end"]:
  298. end_datetime = datetime.strptime(args["end"], "%Y-%m-%d %H:%M")
  299. end_datetime = end_datetime.replace(second=0)
  300. end_datetime_timezone = timezone.localize(end_datetime)
  301. end_datetime_utc = end_datetime_timezone.astimezone(utc_timezone)
  302. sql_query += " AND c.created_at < :end"
  303. arg_dict["end"] = end_datetime_utc
  304. sql_query += """
  305. GROUP BY m.conversation_id
  306. ) subquery
  307. LEFT JOIN
  308. conversations c
  309. ON c.id = subquery.conversation_id
  310. GROUP BY
  311. date
  312. ORDER BY
  313. date"""
  314. response_data = []
  315. with db.engine.begin() as conn:
  316. rs = conn.execute(sa.text(sql_query), arg_dict)
  317. for i in rs:
  318. response_data.append(
  319. {"date": str(i.date), "interactions": float(i.interactions.quantize(Decimal("0.01")))}
  320. )
  321. return jsonify({"data": response_data})
  322. @console_ns.route("/apps/<uuid:app_id>/statistics/user-satisfaction-rate")
  323. class UserSatisfactionRateStatistic(Resource):
  324. @api.doc("get_user_satisfaction_rate_statistics")
  325. @api.doc(description="Get user satisfaction rate statistics for an application")
  326. @api.doc(params={"app_id": "Application ID"})
  327. @api.expect(
  328. api.parser()
  329. .add_argument("start", type=str, location="args", help="Start date (YYYY-MM-DD HH:MM)")
  330. .add_argument("end", type=str, location="args", help="End date (YYYY-MM-DD HH:MM)")
  331. )
  332. @api.response(
  333. 200,
  334. "User satisfaction rate statistics retrieved successfully",
  335. fields.List(fields.Raw(description="User satisfaction rate data")),
  336. )
  337. @get_app_model
  338. @setup_required
  339. @login_required
  340. @account_initialization_required
  341. def get(self, app_model):
  342. account = current_user
  343. parser = reqparse.RequestParser()
  344. parser.add_argument("start", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  345. parser.add_argument("end", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  346. args = parser.parse_args()
  347. sql_query = """SELECT
  348. DATE(DATE_TRUNC('day', m.created_at AT TIME ZONE 'UTC' AT TIME ZONE :tz )) AS date,
  349. COUNT(m.id) AS message_count,
  350. COUNT(mf.id) AS feedback_count
  351. FROM
  352. messages m
  353. LEFT JOIN
  354. message_feedbacks mf
  355. ON mf.message_id=m.id AND mf.rating='like'
  356. WHERE
  357. m.app_id = :app_id
  358. AND m.invoke_from != :invoke_from"""
  359. arg_dict = {"tz": account.timezone, "app_id": app_model.id, "invoke_from": InvokeFrom.DEBUGGER.value}
  360. timezone = pytz.timezone(account.timezone)
  361. utc_timezone = pytz.utc
  362. if args["start"]:
  363. start_datetime = datetime.strptime(args["start"], "%Y-%m-%d %H:%M")
  364. start_datetime = start_datetime.replace(second=0)
  365. start_datetime_timezone = timezone.localize(start_datetime)
  366. start_datetime_utc = start_datetime_timezone.astimezone(utc_timezone)
  367. sql_query += " AND m.created_at >= :start"
  368. arg_dict["start"] = start_datetime_utc
  369. if args["end"]:
  370. end_datetime = datetime.strptime(args["end"], "%Y-%m-%d %H:%M")
  371. end_datetime = end_datetime.replace(second=0)
  372. end_datetime_timezone = timezone.localize(end_datetime)
  373. end_datetime_utc = end_datetime_timezone.astimezone(utc_timezone)
  374. sql_query += " AND m.created_at < :end"
  375. arg_dict["end"] = end_datetime_utc
  376. sql_query += " GROUP BY date ORDER BY date"
  377. response_data = []
  378. with db.engine.begin() as conn:
  379. rs = conn.execute(sa.text(sql_query), arg_dict)
  380. for i in rs:
  381. response_data.append(
  382. {
  383. "date": str(i.date),
  384. "rate": round((i.feedback_count * 1000 / i.message_count) if i.message_count > 0 else 0, 2),
  385. }
  386. )
  387. return jsonify({"data": response_data})
  388. @console_ns.route("/apps/<uuid:app_id>/statistics/average-response-time")
  389. class AverageResponseTimeStatistic(Resource):
  390. @api.doc("get_average_response_time_statistics")
  391. @api.doc(description="Get average response time statistics for an application")
  392. @api.doc(params={"app_id": "Application ID"})
  393. @api.expect(
  394. api.parser()
  395. .add_argument("start", type=str, location="args", help="Start date (YYYY-MM-DD HH:MM)")
  396. .add_argument("end", type=str, location="args", help="End date (YYYY-MM-DD HH:MM)")
  397. )
  398. @api.response(
  399. 200,
  400. "Average response time statistics retrieved successfully",
  401. fields.List(fields.Raw(description="Average response time data")),
  402. )
  403. @setup_required
  404. @login_required
  405. @account_initialization_required
  406. @get_app_model(mode=AppMode.COMPLETION)
  407. def get(self, app_model):
  408. account = current_user
  409. parser = reqparse.RequestParser()
  410. parser.add_argument("start", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  411. parser.add_argument("end", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  412. args = parser.parse_args()
  413. sql_query = """SELECT
  414. DATE(DATE_TRUNC('day', created_at AT TIME ZONE 'UTC' AT TIME ZONE :tz )) AS date,
  415. AVG(provider_response_latency) AS latency
  416. FROM
  417. messages
  418. WHERE
  419. app_id = :app_id
  420. AND invoke_from != :invoke_from"""
  421. arg_dict = {"tz": account.timezone, "app_id": app_model.id, "invoke_from": InvokeFrom.DEBUGGER.value}
  422. timezone = pytz.timezone(account.timezone)
  423. utc_timezone = pytz.utc
  424. if args["start"]:
  425. start_datetime = datetime.strptime(args["start"], "%Y-%m-%d %H:%M")
  426. start_datetime = start_datetime.replace(second=0)
  427. start_datetime_timezone = timezone.localize(start_datetime)
  428. start_datetime_utc = start_datetime_timezone.astimezone(utc_timezone)
  429. sql_query += " AND created_at >= :start"
  430. arg_dict["start"] = start_datetime_utc
  431. if args["end"]:
  432. end_datetime = datetime.strptime(args["end"], "%Y-%m-%d %H:%M")
  433. end_datetime = end_datetime.replace(second=0)
  434. end_datetime_timezone = timezone.localize(end_datetime)
  435. end_datetime_utc = end_datetime_timezone.astimezone(utc_timezone)
  436. sql_query += " AND created_at < :end"
  437. arg_dict["end"] = end_datetime_utc
  438. sql_query += " GROUP BY date ORDER BY date"
  439. response_data = []
  440. with db.engine.begin() as conn:
  441. rs = conn.execute(sa.text(sql_query), arg_dict)
  442. for i in rs:
  443. response_data.append({"date": str(i.date), "latency": round(i.latency * 1000, 4)})
  444. return jsonify({"data": response_data})
  445. @console_ns.route("/apps/<uuid:app_id>/statistics/tokens-per-second")
  446. class TokensPerSecondStatistic(Resource):
  447. @api.doc("get_tokens_per_second_statistics")
  448. @api.doc(description="Get tokens per second statistics for an application")
  449. @api.doc(params={"app_id": "Application ID"})
  450. @api.expect(
  451. api.parser()
  452. .add_argument("start", type=str, location="args", help="Start date (YYYY-MM-DD HH:MM)")
  453. .add_argument("end", type=str, location="args", help="End date (YYYY-MM-DD HH:MM)")
  454. )
  455. @api.response(
  456. 200,
  457. "Tokens per second statistics retrieved successfully",
  458. fields.List(fields.Raw(description="Tokens per second data")),
  459. )
  460. @get_app_model
  461. @setup_required
  462. @login_required
  463. @account_initialization_required
  464. def get(self, app_model):
  465. account = current_user
  466. parser = reqparse.RequestParser()
  467. parser.add_argument("start", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  468. parser.add_argument("end", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")
  469. args = parser.parse_args()
  470. sql_query = """SELECT
  471. DATE(DATE_TRUNC('day', created_at AT TIME ZONE 'UTC' AT TIME ZONE :tz )) AS date,
  472. CASE
  473. WHEN SUM(provider_response_latency) = 0 THEN 0
  474. ELSE (SUM(answer_tokens) / SUM(provider_response_latency))
  475. END as tokens_per_second
  476. FROM
  477. messages
  478. WHERE
  479. app_id = :app_id
  480. AND invoke_from != :invoke_from"""
  481. arg_dict = {"tz": account.timezone, "app_id": app_model.id, "invoke_from": InvokeFrom.DEBUGGER.value}
  482. timezone = pytz.timezone(account.timezone)
  483. utc_timezone = pytz.utc
  484. if args["start"]:
  485. start_datetime = datetime.strptime(args["start"], "%Y-%m-%d %H:%M")
  486. start_datetime = start_datetime.replace(second=0)
  487. start_datetime_timezone = timezone.localize(start_datetime)
  488. start_datetime_utc = start_datetime_timezone.astimezone(utc_timezone)
  489. sql_query += " AND created_at >= :start"
  490. arg_dict["start"] = start_datetime_utc
  491. if args["end"]:
  492. end_datetime = datetime.strptime(args["end"], "%Y-%m-%d %H:%M")
  493. end_datetime = end_datetime.replace(second=0)
  494. end_datetime_timezone = timezone.localize(end_datetime)
  495. end_datetime_utc = end_datetime_timezone.astimezone(utc_timezone)
  496. sql_query += " AND created_at < :end"
  497. arg_dict["end"] = end_datetime_utc
  498. sql_query += " GROUP BY date ORDER BY date"
  499. response_data = []
  500. with db.engine.begin() as conn:
  501. rs = conn.execute(sa.text(sql_query), arg_dict)
  502. for i in rs:
  503. response_data.append({"date": str(i.date), "tps": round(i.tokens_per_second, 4)})
  504. return jsonify({"data": response_data})