MeUtils 2025.4.13.14.49.36__py3-none-any.whl → 2025.4.15.12.6.48__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
meutils/llm/models.py ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # @Project : AI. @by PyCharm
4
+ # @File : models
5
+ # @Time : 2025/4/14 11:09
6
+ # @Author : betterme
7
+ # @WeChat : meutils
8
+ # @Software : PyCharm
9
+ # @Description :
10
+ import os
11
+
12
+ from meutils.pipe import *
13
+ from meutils.llm.clients import OpenAI, AsyncOpenAI
14
+
15
+
16
+ async def check_token(api_key):
17
+ try:
18
+ client = AsyncOpenAI(
19
+ base_url=os.getenv("OPENROUTER_BASE_URL"),
20
+ api_key=api_key,
21
+ )
22
+ r = await client.chat.completions.create(
23
+ messages=[{'role': 'user', 'content': 'hi'}],
24
+ model="google/gemma-3-1b-it:free",
25
+ max_tokens=1,
26
+ stream=False
27
+ )
28
+ logger.debug(r)
29
+ return True
30
+
31
+ except Exception as e:
32
+ logger.error(e)
33
+ return False
34
+
35
+
36
+ async def check_token_for_together(api_key):
37
+ model = "meta-llama/Llama-Vision-Free"
38
+ try:
39
+ client = AsyncOpenAI(
40
+ base_url=os.getenv("TOGETHER_BASE_URL"),
41
+ api_key=api_key,
42
+ )
43
+ r = await client.chat.completions.create(
44
+ messages=[{'role': 'user', 'content': 'hi'}],
45
+ model=model,
46
+ max_tokens=1,
47
+ stream=False
48
+ )
49
+ logger.debug(r)
50
+ return True
51
+
52
+ except Exception as e:
53
+ logger.error(e)
54
+ return False
55
+
56
+
57
+ def get_openrouter_models():
58
+ models = OpenAI(base_url=os.getenv("OPENROUTER_BASE_URL"), api_key='xx').models.list()
59
+
60
+ data = {}
61
+ for model in models.data:
62
+ if model.id.lower().endswith(':free'):
63
+ _model = model.id.lower().removesuffix(":free").split('/')[-1]
64
+ data[_model] = f"""{_model}=={model.id}"""
65
+
66
+ print(data | xjoin(","))
67
+ return data
68
+
69
+
70
+ def get_together_models():
71
+ client = OpenAI(base_url=os.getenv("TOGETHER_BASE_URL"), api_key=os.getenv("TOGETHER_API_KEY"))
72
+ models = client.get("models", cast_to=object)
73
+ # logger.debug(bjson(models))
74
+
75
+ data = {}
76
+ for model in models:
77
+ if model['id'].lower().endswith('-free'):
78
+ _model = model['id'].lower().removesuffix("-free").split('/')[-1]
79
+ data[_model] = f"""{_model}=={model['id']}"""
80
+
81
+ print(data | xjoin(","))
82
+ return data
83
+
84
+
85
+ if __name__ == '__main__':
86
+ from meutils.config_utils.lark_utils import get_series
87
+
88
+ # print(bjson(get_openrouter_models()))
89
+ # print(bjson(get_together_models()))
90
+
91
+ # arun(check_token("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"))
92
+
93
+ # tokens = arun(get_series("https://xchatllm.feishu.cn/sheets/GYCHsvI4qhnDPNtI4VPcdw2knEd?sheet=gGFIXb"))
94
+ #
95
+ # r = []
96
+ # for i in tokens:
97
+ # if not arun(check_token(i)):
98
+ # print(i)
99
+ # r.append(i)
100
+
101
+ feishu_url = "https://xchatllm.feishu.cn/sheets/GYCHsvI4qhnDPNtI4VPcdw2knEd?sheet=tEsIyw"
102
+
103
+ tokens = arun(get_series(feishu_url))
104
+
105
+ r = []
106
+ rr = []
107
+ for i in tokens:
108
+ if not arun(check_token_for_together(i)):
109
+ print(i)
110
+ r.append(i)
111
+ else:
112
+ rr.append(i)
113
+
114
+ # arun(check_token_for_together("1581bb1c605501c96569cf9a24aafa7361752697a23475cdf8f2c3fe8a488292"))
@@ -9,18 +9,67 @@
9
9
  # @Description :
10
10
 
11
11
  from meutils.pipe import *
12
- from meutils.llm.clients import AsyncOpenAI
12
+ from meutils.io.files_utils import to_base64
13
+ from meutils.llm.clients import AsyncOpenAI, zhipuai_client
13
14
  from meutils.llm.openai_utils import to_openai_params
14
15
 
15
16
  from meutils.schemas.openai_types import CompletionRequest
16
17
 
18
+ from meutils.apis.proxy.kdlapi import get_one_proxy
19
+
17
20
 
18
21
  class Completions(object):
19
22
 
20
23
  def __init__(self, base_url: Optional[str] = None, api_key: Optional[str] = None):
21
- self.client = AsyncOpenAI(base_url=base_url, api_key=api_key)
24
+ self.base_url = base_url
25
+ self.api_key = api_key
26
+
27
+ self.client = AsyncOpenAI(base_url=self.base_url, api_key=self.api_key)
28
+
29
+ # http_client = None
30
+ # if request.user == 'proxy':
31
+ # http_client = httpx.AsyncClient(proxy=await get_one_proxy(), timeout=60)
22
32
 
23
33
  async def create(self, request: CompletionRequest):
34
+
35
+ if request.user == 'proxy':
36
+ http_client = httpx.AsyncClient(proxy=await get_one_proxy(), timeout=120)
37
+ self.client = AsyncOpenAI(base_url=self.base_url, api_key=self.api_key, http_client=http_client)
38
+
39
+ ###########################################################################
40
+
41
+ # 开启视觉模型
42
+ if not any(i in request.model for i in ["vl", 'vision']) and (urls := request.last_urls.get("image_url")):
43
+ # logger.debug(request)
44
+ if request.model.startswith(("gemini",)): # 仅支持base64
45
+ base64_list = await to_base64(urls, content_type="image/png") ######## todo: tokens怎么计算的
46
+ request.messages = [
47
+ {
48
+ 'role': 'user',
49
+ 'content': [
50
+ {
51
+ 'type': 'text',
52
+ 'text': request.last_user_content
53
+ },
54
+ *[
55
+ {
56
+ 'type': 'image_url',
57
+ 'image_url': {
58
+ 'url': base64_data
59
+ }
60
+ }
61
+ for base64_data in base64_list
62
+ ]
63
+
64
+ ]
65
+ }
66
+ ]
67
+ else:
68
+ # logger.debug('xxxxxxxx')
69
+ request.model = "glm-4v-flash"
70
+ self.client = zhipuai_client
71
+ ###########################################################################
72
+
24
73
  data = to_openai_params(request)
25
74
  if 'gemini' in request.model:
26
75
  data.pop("seed", None)
@@ -32,14 +81,38 @@ class Completions(object):
32
81
 
33
82
 
34
83
  if __name__ == '__main__':
35
- # 测试
84
+ # 测试 token 1800
36
85
 
37
86
  request = CompletionRequest(
38
- model="gpt-4o-mini",
87
+ # model="gemini-2.0-flash",
88
+ model="glm-4-flash",
89
+
39
90
  messages=[
40
- {"role": "system", "content": "你是一个助手"},
41
- {"role": "user", "content": "你好"}
91
+ {
92
+ "role": "system",
93
+ "content": [
94
+ {
95
+ "type": "text",
96
+ "text": "你是一个数学助手,擅长解决复杂的数学问题。"
97
+ }
98
+ ]
99
+ },
100
+ # {"role": "user", "content": "你好"},
101
+ {"role": "user", "content": [
102
+ {
103
+ "type": "text",
104
+ "text": "解释下"
105
+ },
106
+ {
107
+ "image_url": {
108
+ "detail": "auto",
109
+ "url": "https://osshk.share704.com/file/upload/2025/04/14/1911575959253815296.jpg"
110
+ },
111
+ "type": "image_url"
112
+ }
113
+ ]}
42
114
  ],
43
- stream=False
115
+ stream=False,
116
+ max_tokens=8000,
44
117
  )
45
118
  arun(Completions().create(request))
@@ -26,6 +26,9 @@ MODEL_PRICE = {
26
26
  "black-forest-labs/FLUX.1-dev": 0.0001,
27
27
  "black-forest-labs/FLUX.1-pro": 0.0001,
28
28
 
29
+ "gemini-2.0-flash-search": 0.01,
30
+ "gemini-2.0-flash-exp-image-generation": 0.03,
31
+
29
32
  "images": FREE,
30
33
  # rix
31
34
  "kling_image": 0.05,
@@ -51,9 +54,6 @@ MODEL_PRICE = {
51
54
  "minimax_video-01-live2d": MINIMAX_VIDEO,
52
55
 
53
56
  # free
54
- "google/gemini-2.0-flash-thinking-exp:free": 0.00001,
55
- "google/gemini-2.0-flash-lite-preview-02-05:free": 0.00001,
56
- "google/gemini-2.0-pro-exp-02-05:free": 0.00001,
57
57
 
58
58
  # chatfire
59
59
  "ppu-0001": 0.0001,
@@ -415,9 +415,18 @@ MODEL_RATIO = {
415
415
  "glm-zero-preview": 5,
416
416
 
417
417
  # 月之暗面 https://platform.moonshot.cn/docs/price/chat#%E4%BA%A7%E5%93%81%E5%AE%9A%E4%BB%B7
418
- "moonshot-v1-8k": 6 / 2, # 特价
419
- "moonshot-v1-32k": 12 / 2, # 特价
420
- "moonshot-v1-128k": 60 / 2, # 特价
418
+ "kimi-latest-8k ": 1,
419
+ "kimi-latest-32k": 2.5,
420
+ "kimi-latest-128k": 5,
421
+
422
+ "moonshot-v1-8k": 1,
423
+ "moonshot-v1-32k": 2.5,
424
+ "moonshot-v1-128k": 5,
425
+
426
+ "kimi-vl-a3b-thinking": 1,
427
+ "moonshot-v1-8k-vision-preview": 1,
428
+ "moonshot-v1-32k-vision-preview": 2.5,
429
+ "moonshot-v1-128k-vision-preview": 5,
421
430
 
422
431
  # 阿里千问 https://dashscope.console.aliyun.com/billing
423
432
  "qwen-long": 0.25,
@@ -517,6 +526,8 @@ MODEL_RATIO = {
517
526
  # deepseek
518
527
  "deepseek-v3": 1,
519
528
  "deepseek-v3-0324": 1,
529
+ "deepseek-v3-250324": 1,
530
+
520
531
  "deepseek-v3-8k": 0.5,
521
532
  "deepseek-v3-128k": 5,
522
533
  "deepseek-chat": 1,
@@ -687,8 +698,6 @@ MODEL_RATIO = {
687
698
  "gemini-2.0-flash-001": 0.0625,
688
699
  "gemini-2.0-flash-lite-preview-02-05": 0.0625,
689
700
  "gemini-2.0-flash-exp": 0.0625,
690
- "gemini-2.0-flash-exp-image": 2.5,
691
- "gemini-2.0-flash-exp-image-generation": 2.5,
692
701
 
693
702
  "gemini-2.0-pro": 1.25,
694
703
  "gemini-2.0-pro-exp-02-05": 1.25,
@@ -749,6 +758,13 @@ MODEL_RATIO = {
749
758
  "gpt-4o-2024-11-20": 1.25,
750
759
  "gpt-4.5-preview-2025-02-27": 37.5,
751
760
 
761
+ "gpt-4.1": 1,
762
+ "gpt-4.1-mini": 0.2,
763
+ "gpt-4.1-nano": 0.05,
764
+ "gpt-4.1-2025-04-14": 1,
765
+ "gpt-4.1-mini-2025-04-14": 0.2,
766
+ "gpt-4.1-nano-2025-04-14": 0.05,
767
+
752
768
  "o1": 7.5,
753
769
  "o1-2024-12-17": 7.5,
754
770
 
@@ -787,6 +803,7 @@ MODEL_RATIO = {
787
803
 
788
804
  "internlm2_5-7b-chat": 0.01,
789
805
  'internlm2_5-20b-chat': 0.5,
806
+ "internlm3-8b-instruct": 0.25,
790
807
 
791
808
  "acge_text_embedding": 1,
792
809
  "dmeta-embedding-zh-q4": 1,
@@ -820,6 +837,20 @@ COMPLETION_RATIO = {
820
837
  "deepresearch": 4,
821
838
  "deepsearch": 4,
822
839
 
840
+ # kimi
841
+ "kimi-latest-8k ": 5,
842
+ "kimi-latest-32k": 4,
843
+ "kimi-latest-128k": 3,
844
+
845
+ "moonshot-v1-8k": 5,
846
+ "moonshot-v1-32k": 4,
847
+ "moonshot-v1-128k": 3,
848
+
849
+ "kimi-vl-a3b-thinking": 5,
850
+ "moonshot-v1-8k-vision-preview": 5,
851
+ "moonshot-v1-32k-vision-preview": 4,
852
+ "moonshot-v1-128k-vision-preview": 3,
853
+
823
854
  "grok-2": 5,
824
855
  "grok-2-1212": 5,
825
856
  "grok-2-vision-1212": 5,
@@ -856,6 +887,14 @@ COMPLETION_RATIO = {
856
887
 
857
888
  "gpt-4o-audio-preview": 4,
858
889
  "gpt-4o-audio-preview-2024-12-17": 4,
890
+
891
+ "gpt-4.1": 4,
892
+ "gpt-4.1-mini": 4,
893
+ "gpt-4.1-nano": 4,
894
+ "gpt-4.1-2025-04-14": 4,
895
+ "gpt-4.1-mini-2025-04-14": 4,
896
+ "gpt-4.1-nano-2025-04-14": 4,
897
+
859
898
  "gemini-2.0-flash-audio": 4,
860
899
 
861
900
  # claude
@@ -911,8 +950,6 @@ COMPLETION_RATIO = {
911
950
  "gemini-2.0-flash-001": 4,
912
951
 
913
952
  "gemini-2.0-flash-exp": 5,
914
- "gemini-2.0-flash-exp-image": 5,
915
- "gemini-2.0-flash-exp-image-generation": 5,
916
953
 
917
954
  "gemini-2.0-flash-thinking-exp": 5,
918
955
  "gemini-2.0-flash-thinking-exp-1219": 5,
@@ -1018,6 +1055,7 @@ COMPLETION_RATIO = {
1018
1055
 
1019
1056
  "deepseek-v3": 4,
1020
1057
  "deepseek-v3-0324": 4,
1058
+ "deepseek-v3-250324": 4,
1021
1059
  "deepseek-chat": 4,
1022
1060
 
1023
1061
  'deepseek-r1': 4,
@@ -603,10 +603,10 @@ if __name__ == '__main__':
603
603
  # print(chat_completion_chunk_stop)
604
604
 
605
605
  # print(CompletionRequest(messages=messages).last_urls)
606
- # print(CompletionRequest(messages=messages).last_urls)
606
+ print(CompletionRequest(messages=messages).last_urls)
607
607
 
608
608
  # print(mesages)
609
- print(CompletionRequest(messages=messages).last_assistant_content)
609
+ # print(CompletionRequest(messages=messages).last_assistant_content)
610
610
 
611
611
  # print(chat_completion_chunk)
612
612
  # print(chat_completion)
@@ -36,7 +36,7 @@ async def get_bearer_token(
36
36
  if token.startswith('redis:'): # redis里按序轮询
37
37
  if "feishu.cn" in token:
38
38
  feishu_url = token.removeprefix("redis:")
39
- token = await get_next_token(feishu_url) # todo: 摆脱 feishu
39
+ token = await get_next_token(feishu_url, ttl=24 * 3600) # todo: 摆脱 feishu
40
40
 
41
41
  # logger.debug(token)
42
42