You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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