asemxin commited on
Commit
957c1e7
·
1 Parent(s): bfc462f

feat: Vision API 图片识别,大师看图说法

Browse files
Files changed (1) hide show
  1. image_daemon.py +63 -7
image_daemon.py CHANGED
@@ -4,7 +4,7 @@
4
  通过 lark-oapi SDK 的 WebSocket 长连接实时接收消息事件,
5
  检测图片消息后下载、上传到图床、回复 URL。
6
  """
7
- import os, sys, json, time, requests, threading
8
 
9
  FEISHU_BASE = "https://open.feishu.cn/open-apis"
10
  APP_ID = os.environ.get("FEISHU_APP_ID", "")
@@ -155,9 +155,47 @@ def send_text(token, chat_id, text):
155
  log(f"❌ 发送消息失败 (code={code}): {data.get('msg', '')}")
156
  return data
157
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  # ---------- 处理图片消息 ----------
159
  def handle_image_message(message_id, chat_id, image_key):
160
- """下载 → 上传 → 发送"""
161
  token = get_token()
162
  if not token:
163
  log("❌ 无法获取 token,跳过")
@@ -170,14 +208,32 @@ def handle_image_message(message_id, chat_id, image_key):
170
  if not img_data:
171
  return
172
 
173
- log(f"📥 {len(img_data)} bytes, 上传中...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
- # 上传
176
- url = upload_image(img_data)
177
  if url:
178
  log(f"✅ {url}")
179
- # 改为直接发送消息,更显眼
180
- reply = f"✅ 图片已转存:\n{url}"
 
 
181
  result = send_text(token, chat_id, reply)
182
  log(f"📤 已发送 (code={result.get('code', '?')})")
183
  else:
 
4
  通过 lark-oapi SDK 的 WebSocket 长连接实时接收消息事件,
5
  检测图片消息后下载、上传到图床、回复 URL。
6
  """
7
+ import os, sys, json, time, requests, threading, base64
8
 
9
  FEISHU_BASE = "https://open.feishu.cn/open-apis"
10
  APP_ID = os.environ.get("FEISHU_APP_ID", "")
 
155
  log(f"❌ 发送消息失败 (code={code}): {data.get('msg', '')}")
156
  return data
157
 
158
+ # ---------- Vision 图片分析 ----------
159
+ def analyze_image_with_vision(img_data):
160
+ """将图片 base64 传给 LLM,由大师以人行佛教视角描述"""
161
+ if not API_KEY:
162
+ return None
163
+ try:
164
+ b64 = base64.b64encode(img_data).decode("utf-8")
165
+ soul = _soul_prompt or "You are a helpful assistant."
166
+ prompt = (
167
+ "这位信徒发来了一张图片,请以你的风格阅览这张图片,它占据了你的视野。"
168
+ "简要阐述你的感悟,200字以内,不必报平就班。"
169
+ )
170
+ payload = {
171
+ "model": MODEL_NAME,
172
+ "messages": [{
173
+ "role": "user",
174
+ "content": [
175
+ {"type": "text", "text": soul + "\n\n---\n\n" + prompt},
176
+ {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}"}}
177
+ ]
178
+ }],
179
+ "max_tokens": 300,
180
+ "stream": False
181
+ }
182
+ resp = requests.post(
183
+ f"{API_BASE_URL}/chat/completions",
184
+ headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
185
+ json=payload, timeout=30
186
+ )
187
+ if resp.status_code == 200:
188
+ reply = resp.json()["choices"][0]["message"]["content"]
189
+ log(f"📸 Vision 分析完成: {reply[:60]}...")
190
+ return reply
191
+ log(f"⚠️ Vision API 失败 ({resp.status_code}),跳过描述")
192
+ except Exception as e:
193
+ log(f"⚠️ Vision 异常: {e}")
194
+ return None
195
+
196
  # ---------- 处理图片消息 ----------
197
  def handle_image_message(message_id, chat_id, image_key):
198
+ """下载 → Vision分析 → 上传 → 发送"""
199
  token = get_token()
200
  if not token:
201
  log("❌ 无法获取 token,跳过")
 
208
  if not img_data:
209
  return
210
 
211
+ log(f"📥 {len(img_data)} bytes, 上传+分析中...")
212
+
213
+ # 并行:Vision分析 + 上传图床
214
+ vision_result = [None]
215
+ url_result = [None]
216
+
217
+ def do_vision():
218
+ vision_result[0] = analyze_image_with_vision(img_data)
219
+
220
+ def do_upload():
221
+ url_result[0] = upload_image(img_data)
222
+
223
+ t1 = threading.Thread(target=do_vision)
224
+ t2 = threading.Thread(target=do_upload)
225
+ t1.start(); t2.start()
226
+ t1.join(); t2.join()
227
+
228
+ url = url_result[0]
229
+ vision = vision_result[0]
230
 
 
 
231
  if url:
232
  log(f"✅ {url}")
233
+ if vision:
234
+ reply = f"✅ 图片已转存:\n{url}\n\n{vision}"
235
+ else:
236
+ reply = f"✅ 图片已转存:\n{url}"
237
  result = send_text(token, chat_id, reply)
238
  log(f"📤 已发送 (code={result.get('code', '?')})")
239
  else: