Skip to content

Commit 69f6832

Browse files
authored
fix: restore language translation,and token/s display
1 parent d1724fe commit 69f6832

File tree

1 file changed

+63
-37
lines changed

1 file changed

+63
-37
lines changed

resources/functions/openwebui_monitor.py

+63-37
Original file line numberDiff line numberDiff line change
@@ -8,46 +8,78 @@
88
"""
99

1010
import logging
11+
import time
1112
from typing import Dict, Optional
12-
1313
from httpx import AsyncClient
1414
from pydantic import BaseModel, Field
1515

1616
logger = logging.getLogger(__name__)
1717
logger.setLevel(logging.INFO)
1818

19+
TRANSLATIONS = {
20+
"en": {
21+
"request_failed": "Request failed: {error_msg}",
22+
"insufficient_balance": "Insufficient balance: Current balance `{balance:.4f}`",
23+
"cost": "Cost: ${cost:.4f}",
24+
"balance": "Balance: ${balance:.4f}",
25+
"tokens": "Tokens: {input}+{output}",
26+
"time_spent": "Time: {time:.2f}s",
27+
"tokens_per_sec": "{tokens_per_sec:.2f} T/s"
28+
},
29+
"zh": {
30+
"request_failed": "请求失败: {error_msg}",
31+
"insufficient_balance": "余额不足: 当前余额 `{balance:.4f}`",
32+
"cost": "费用: ¥{cost:.4f}",
33+
"balance": "余额: ¥{balance:.4f}",
34+
"tokens": "Token: {input}+{output}",
35+
"time_spent": "耗时: {time:.2f}s",
36+
"tokens_per_sec": "{tokens_per_sec:.2f} T/s"
37+
}
38+
}
1939

2040
class CustomException(Exception):
2141
pass
2242

23-
2443
class Filter:
2544
class Valves(BaseModel):
2645
api_endpoint: str = Field(default="", description="openwebui-monitor's base url")
2746
api_key: str = Field(default="", description="openwebui-monitor's api key")
2847
priority: int = Field(default=5, description="filter priority")
48+
language: str = Field(default="zh", description="language (en/zh)")
49+
show_time_spent: bool = Field(default=True, description="show time spent")
50+
show_tokens_per_sec: bool = Field(default=True, description="show tokens per second")
51+
show_cost: bool = Field(default=True, description="show cost")
52+
show_balance: bool = Field(default=True, description="show balance")
53+
show_tokens: bool = Field(default=True, description="show tokens")
2954

3055
def __init__(self):
3156
self.type = "filter"
57+
self.name = "OpenWebUI Monitor"
3258
self.valves = self.Valves()
3359
self.outage_map: Dict[str, bool] = {}
60+
self.start_time: Optional[float] = None
61+
62+
def get_text(self, key: str, **kwargs) -> str:
63+
lang = self.valves.language if self.valves.language in TRANSLATIONS else "en"
64+
text = TRANSLATIONS[lang].get(key, TRANSLATIONS["en"][key])
65+
return text.format(**kwargs) if kwargs else text
3466

3567
async def request(self, client: AsyncClient, url: str, headers: dict, json: dict):
3668
response = await client.post(url=url, headers=headers, json=json)
3769
response.raise_for_status()
3870
response_data = response.json()
3971
if not response_data.get("success"):
40-
logger.error("[usage_monitor] req monitor failed: %s", response_data)
41-
raise CustomException("calculate usage failed, please contact administrator")
72+
logger.error(self.get_text("request_failed", error_msg=response_data))
73+
raise CustomException(self.get_text("request_failed", error_msg=response_data))
4274
return response_data
4375

4476
async def inlet(self, body: dict, __metadata__: Optional[dict] = None, __user__: Optional[dict] = None) -> dict:
4577
__user__ = __user__ or {}
4678
__metadata__ = __metadata__ or {}
47-
user_id = __user__["id"]
79+
self.start_time = time.time()
80+
user_id = __user__.get("id", "default")
4881

4982
client = AsyncClient()
50-
5183
try:
5284
response_data = await self.request(
5385
client=client,
@@ -57,36 +89,26 @@ async def inlet(self, body: dict, __metadata__: Optional[dict] = None, __user__:
5789
)
5890
self.outage_map[user_id] = response_data.get("balance", 0) <= 0
5991
if self.outage_map[user_id]:
60-
logger.info("[usage_monitor] no balance: %s", user_id)
61-
raise CustomException("no balance, please contact administrator")
62-
92+
logger.info(self.get_text("insufficient_balance", balance=response_data.get("balance", 0)))
93+
raise CustomException(self.get_text("insufficient_balance", balance=response_data.get("balance", 0)))
6394
return body
64-
6595
except Exception as err:
66-
logger.exception("[usage_monitor] error calculating usage: %s", err)
96+
logger.exception(self.get_text("request_failed", error_msg=err))
6797
if isinstance(err, CustomException):
6898
raise err
6999
raise Exception(f"error calculating usage, {err}") from err
70-
71100
finally:
72101
await client.aclose()
73102

74-
async def outlet(
75-
self,
76-
body: dict,
77-
__metadata__: Optional[dict] = None,
78-
__user__: Optional[dict] = None,
79-
__event_emitter__: callable = None,
80-
) -> dict:
103+
async def outlet(self, body: dict, __metadata__: Optional[dict] = None, __user__: Optional[dict] = None, __event_emitter__: Optional[callable] = None) -> dict:
81104
__user__ = __user__ or {}
82105
__metadata__ = __metadata__ or {}
83-
user_id = __user__["id"]
106+
user_id = __user__.get("id", "default")
84107

85-
if self.outage_map[user_id]:
108+
if self.outage_map.get(user_id, False):
86109
return body
87110

88111
client = AsyncClient()
89-
90112
try:
91113
response_data = await self.request(
92114
client=client,
@@ -95,23 +117,27 @@ async def outlet(
95117
json={"user": __user__, "body": body},
96118
)
97119

98-
# pylint: disable=C0209
99-
stats = " | ".join(
100-
[
101-
f"Tokens: {response_data['inputTokens']} + {response_data['outputTokens']}",
102-
"Cost: %.4f" % response_data["totalCost"],
103-
"Balance: %.4f" % response_data["newBalance"],
104-
]
105-
)
106-
107-
await __event_emitter__({"type": "status", "data": {"description": stats, "done": True}})
108-
120+
stats_list = []
121+
if self.valves.show_tokens:
122+
stats_list.append(self.get_text("tokens", input=response_data['inputTokens'], output=response_data['outputTokens']))
123+
if self.valves.show_cost:
124+
stats_list.append(self.get_text("cost", cost=response_data["totalCost"]))
125+
if self.valves.show_balance:
126+
stats_list.append(self.get_text("balance", balance=response_data["newBalance"]))
127+
if self.start_time and self.valves.show_time_spent:
128+
elapsed = time.time() - self.start_time
129+
stats_list.append(self.get_text("time_spent", time=elapsed))
130+
if self.valves.show_tokens_per_sec:
131+
tokens_per_sec = response_data['outputTokens'] / elapsed if elapsed > 0 else 0
132+
stats_list.append(self.get_text("tokens_per_sec", tokens_per_sec=tokens_per_sec))
133+
134+
stats = " | ".join(stats_list)
135+
if __event_emitter__:
136+
await __event_emitter__({"type": "status", "data": {"description": stats, "done": True}})
109137
logger.info("usage_monitor: %s %s", user_id, stats)
110138
return body
111-
112139
except Exception as err:
113-
logger.exception("[usage_monitor] error calculating usage: %s", err)
114-
raise Exception(f"error calculating usage, {err}") from err
115-
140+
logger.exception(self.get_text("request_failed", error_msg=err))
141+
raise Exception(self.get_text("request_failed", error_msg=err))
116142
finally:
117143
await client.aclose()

0 commit comments

Comments
 (0)