prxyasd commited on
Commit
bda97e5
Β·
verified Β·
1 Parent(s): 16d445c

Update vertexLib.py

Browse files
Files changed (1) hide show
  1. vertexLib.py +102 -75
vertexLib.py CHANGED
@@ -2,46 +2,13 @@ import json
2
  import time
3
  import requests
4
  import jwt
5
- import aiohttp
6
-
7
 
8
  # ─────────────────────────────────────────
9
- # 곡톡: 응닡을 μ„Έ κ°€μ§€λ‘œ μΆ•μ•½ν•΄μ„œ ν‘œμ‹œ
10
- # "True" β†’ 정상
11
- # "exceed" β†’ μΏΌν„°β€§λ ˆμ΄νŠΈλ¦¬λ°‹ 초과
12
- # "False" β†’ κ·Έ μ™Έ μ‹€νŒ¨
13
- # ─────────────────────────────────────────
14
- def _classify_response(resp: requests.Response) -> str:
15
- if resp.status_code == 200:
16
- return "True"
17
-
18
- try:
19
- err = resp.json().get("error", {})
20
- code = err.get("code", 0)
21
- msg = str(err.get("message", "")).lower()
22
-
23
- if code == 429 or "quota" in msg or "rate" in msg or "exceed" in msg:
24
- return "exceed"
25
- except Exception:
26
- pass
27
-
28
- return "False"
29
-
30
-
31
- def _classify_async_status(code: int, text: str) -> str:
32
- if code == 200:
33
- return "True"
34
- if code == 429 or any(kw in text.lower() for kw in ("quota", "rate", "exceed")):
35
- return "exceed"
36
- return "False"
37
-
38
-
39
- # ─────────────────────────────────────────
40
- # 1) μ„œλΉ„μŠ€ 계정 β†’ μ•‘μ„ΈμŠ€ 토큰
41
  # ─────────────────────────────────────────
42
  def get_access_token(client_email, private_key):
43
  current_time = int(time.time())
44
- expiration_time = current_time + 600
45
 
46
  claims = {
47
  "iss": client_email,
@@ -54,9 +21,9 @@ def get_access_token(client_email, private_key):
54
  try:
55
  signed_jwt = jwt.encode(claims, private_key, algorithm="RS256")
56
  except Exception as e:
57
- return "False", f"JWT encode error: {e}"
58
 
59
- resp = requests.post(
60
  "https://oauth2.googleapis.com/token",
61
  data={
62
  "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
@@ -64,80 +31,140 @@ def get_access_token(client_email, private_key):
64
  },
65
  )
66
 
67
- return _classify_response(resp), resp.json().get("access_token", resp.text)
 
 
 
68
 
69
 
70
  # ─────────────────────────────────────────
71
- # 2) refresh_token β†’ μ•‘μ„ΈμŠ€ 토큰
72
  # ─────────────────────────────────────────
73
  def get_access_token_refresh(client_id, client_secret, refresh_token):
74
- resp = requests.post(
75
- "https://oauth2.googleapis.com/token",
76
- data={
77
- "client_id": client_id,
78
- "client_secret": client_secret,
79
- "refresh_token": refresh_token,
80
- "grant_type": "refresh_token",
81
- },
82
- )
83
 
84
- return _classify_response(resp), resp.json().get("access_token", resp.text)
 
 
 
85
 
86
 
87
  # ─────────────────────────────────────────
88
- # 3) Gemini λͺ¨λΈ λͺ©λ‘ (κ°„μ†Œν™”)
89
- # 성곡 μ—¬λΆ€λ§Œ λ°˜ν™˜
90
  # ─────────────────────────────────────────
91
- def get_gemini_models(key):
92
- url = f"https://generativelanguage.googleapis.com/v1beta/models?key={key}&pageSize=1"
93
- resp = requests.get(url)
94
- return _classify_response(resp)
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
 
97
  # ─────────────────────────────────────────
98
- # 4) Gemini 더미 호좜 (μΏΌν„° 체크)
99
  # ─────────────────────────────────────────
100
- def send_fake_gemini_request(key, model="gemini-1.5-flash"):
 
 
 
 
101
  url = f"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent?key={key}"
102
  payload = {
103
  "contents": [{"role": "user", "parts": [{"text": ""}]}],
104
  "generationConfig": {"maxOutputTokens": 0},
105
  }
106
-
107
  try:
108
  resp = requests.post(url, headers={"Content-Type": "application/json"}, json=payload)
109
- return _classify_response(resp)
110
  except Exception:
111
- return "False"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
 
114
  # ─────────────────────────────────────────
115
- # 5) Gemini μ‹€μ œ 호좜 (μš”μ•½ μƒνƒœ λ°˜ν™˜)
116
  # ─────────────────────────────────────────
117
- def send_gemini_request(key, payload, model="gemini-1.5-flash"):
118
  url = f"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent?key={key}"
119
  resp = requests.post(url, headers={"Content-Type": "application/json"}, json=payload)
120
- return _classify_response(resp), resp.json() if resp.status_code == 200 else resp.text
 
 
 
 
121
 
122
 
123
  # ─────────────────────────────────────────
124
- # 6) Vertex AI + Anthropic (streamRawPredict)
125
- # μƒνƒœλ§Œ κ°„μ†Œν™”ν•΄ λ°˜ν™˜
126
  # ─────────────────────────────────────────
127
  async def send_gcp_request(
128
- session: aiohttp.ClientSession,
129
- project_id: str,
130
- access_token: str,
131
- payload: str,
132
- region: str = "us-east5",
133
- model: str = "claude-3-5-sonnet@20240620",
134
  ):
135
- url = f"https://{region}-aiplatform.googleapis.com/v1/projects/{project_id}/locations/{region}/publishers/anthropic/models/{model}:streamRawPredict"
 
 
 
136
  headers = {
137
  "Authorization": f"Bearer {access_token}",
138
  "Content-Type": "application/json; charset=utf-8",
139
  }
140
 
141
- async with session.post(url, headers=headers, data=payload) as resp:
142
- text = await resp.text()
143
- return _classify_async_status(resp.status, text), text
 
 
2
  import time
3
  import requests
4
  import jwt
 
 
5
 
6
  # ─────────────────────────────────────────
7
+ # 1. GCP μ„œλΉ„μŠ€κ³„μ • μ•‘μ„ΈμŠ€ 토큰
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  # ─────────────────────────────────────────
9
  def get_access_token(client_email, private_key):
10
  current_time = int(time.time())
11
+ expiration_time = current_time + 600 # 10 λΆ„
12
 
13
  claims = {
14
  "iss": client_email,
 
21
  try:
22
  signed_jwt = jwt.encode(claims, private_key, algorithm="RS256")
23
  except Exception as e:
24
+ return False, e
25
 
26
+ response = requests.post(
27
  "https://oauth2.googleapis.com/token",
28
  data={
29
  "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
 
31
  },
32
  )
33
 
34
+ if response.status_code == 200:
35
+ return True, response.json()["access_token"]
36
+ else:
37
+ return False, response.text
38
 
39
 
40
  # ─────────────────────────────────────────
41
+ # 2. GCP refresh-token μ•‘μ„ΈμŠ€ 토큰
42
  # ─────────────────────────────────────────
43
  def get_access_token_refresh(client_id, client_secret, refresh_token):
44
+ token_url = "https://oauth2.googleapis.com/token"
45
+ data = {
46
+ "client_id": client_id,
47
+ "client_secret": client_secret,
48
+ "refresh_token": refresh_token,
49
+ "grant_type": "refresh_token",
50
+ }
51
+
52
+ response = requests.post(token_url, data=data)
53
 
54
+ if response.status_code == 200:
55
+ return True, response.json()["access_token"]
56
+ else:
57
+ return False, response.text
58
 
59
 
60
  # ─────────────────────────────────────────
61
+ # 3. (선택) λͺ¨λΈ λͺ©λ‘ 쑰회 – μ΅œλŒ€ 10개만 λ°˜ν™˜
 
62
  # ─────────────────────────────────────────
63
+ def get_gemini_models(key, max_return: int = 1):
64
+ """
65
+ λͺ¨λΈμ΄ λ„ˆλ¬΄ λ§Žμ•„ 가독성이 λ–¨μ–΄μ§€λ―€λ‘œ,
66
+ 기본적으둜 10κ°œκΉŒμ§€λ§Œ λ°˜ν™˜ν•˜κ³  λ‚˜λ¨Έμ§€λŠ” 개수둜 μš”μ•½.
67
+ """
68
+ url = f"https://generativelanguage.googleapis.com/v1beta/models?key={key}&pageSize=1000"
69
+ response = requests.get(url)
70
+
71
+ if response.status_code != 200:
72
+ return ""
73
+
74
+ models = response.json().get("models", [])
75
+ names = [m["name"].split("/")[1] for m in models]
76
+ #if len(names) > max_return:
77
+ # return names[:max_return] + [f"...(+{len(names)-max_return})"]
78
+ return None
79
 
80
 
81
  # ─────────────────────────────────────────
82
+ # 4. β€œλ”οΏ½οΏ½οΏ½β€ μš”μ²­μœΌλ‘œ ν‚€ μƒνƒœλ§Œ νŒλ³„
83
  # ─────────────────────────────────────────
84
+ def send_fake_gemini_request(key, model: str = "gemini-1.5-flash"):
85
+ """
86
+ ν”„λ‘¬ν”„νŠΈλ₯Ό 빈 λ¬Έμžμ—΄λ‘œ 보내 κ°„λ‹¨νžˆ ν‚€ μœ νš¨μ„±μ„ 체크.
87
+ λ°˜ν™˜κ°’: error dict | '' | None
88
+ """
89
  url = f"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent?key={key}"
90
  payload = {
91
  "contents": [{"role": "user", "parts": [{"text": ""}]}],
92
  "generationConfig": {"maxOutputTokens": 0},
93
  }
 
94
  try:
95
  resp = requests.post(url, headers={"Content-Type": "application/json"}, json=payload)
96
+ return resp.json().get("error", "")
97
  except Exception:
98
+ return None
99
+
100
+
101
+ def check_key_gemini_availability(key):
102
+ """
103
+ β–Ά λ°˜ν™˜: (bool, str)
104
+ β€’ (True, 'ok') : ν‚€ 유효, μ‚¬μš© κ°€λŠ₯
105
+ β€’ (False, 'exceed') : quota / rate-limit 초과
106
+ β€’ (False, 'invalid') : 잘λͺ»λœ ν‚€ ν˜Ήμ€ κΆŒν•œ μ—†μŒ
107
+ β€’ (False, 'error') : 기타 λ„€νŠΈμ›Œν¬/μ•Œ 수 μ—†λŠ” 였λ₯˜
108
+ """
109
+ err = send_fake_gemini_request(key)
110
+
111
+ # λ„€νŠΈμ›Œν¬ μ‹€νŒ¨
112
+ if err is None:
113
+ return False, "error"
114
+
115
+ # μ—λŸ¬ ν•„λ“œκ°€ μ—†μœΌλ©΄ 정상
116
+ if err == "":
117
+ return True, "ok"
118
+
119
+ # μ—λŸ¬ 객체 뢄석
120
+ code = err.get("code", 0)
121
+ status = err.get("status", "")
122
+
123
+ # 빈 ν”„λ‘¬ν”„νŠΈ λ•Œλ¬Έμ— INVALID_ARGUMENTκ°€ λœ¨λŠ” 경우 β†’ ν‚€λŠ” 정상
124
+ if status == "INVALID_ARGUMENT":
125
+ return True, "ok"
126
+
127
+ # quota 초과
128
+ if code == 429 or status == "RESOURCE_EXHAUSTED":
129
+ return False, "exceed"
130
+
131
+ # κΆŒν•œ/인증 문제
132
+ if code in (401, 403) or status in ("PERMISSION_DENIED", "UNAUTHENTICATED"):
133
+ return False, "invalid"
134
+
135
+ # 기타
136
+ return False, "error"
137
 
138
 
139
  # ─────────────────────────────────────────
140
+ # 5. μ‹€μ œ Gemini μš”μ²­
141
  # ─────────────────────────────────────────
142
+ def send_gemini_request(key, payload, model: str = "gemini-1.5-flash"):
143
  url = f"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent?key={key}"
144
  resp = requests.post(url, headers={"Content-Type": "application/json"}, json=payload)
145
+
146
+ if resp.status_code == 200:
147
+ return True, resp.json()
148
+ else:
149
+ return False, resp.text
150
 
151
 
152
  # ─────────────────────────────────────────
153
+ # 6. Vertex AI (Anthropic) μš”μ²­ – 비동기
 
154
  # ─────────────────────────────────────────
155
  async def send_gcp_request(
156
+ session, project_id, access_token, payload, region="us-east5", model="claude-3-5-sonnet@20240620"
 
 
 
 
 
157
  ):
158
+ VERTEX_URL = (
159
+ f"https://{region}-aiplatform.googleapis.com/v1/projects/"
160
+ f"{project_id}/locations/{region}/publishers/anthropic/models/{model}:streamRawPredict"
161
+ )
162
  headers = {
163
  "Authorization": f"Bearer {access_token}",
164
  "Content-Type": "application/json; charset=utf-8",
165
  }
166
 
167
+ async with session.post(url=VERTEX_URL, headers=headers, data=payload) as response:
168
+ if response.status != 200:
169
+ return json.loads(await response.text())
170
+ return await response.json()