From b9addbf3f159c8e7673f2e9ecc3fa78e73283182 Mon Sep 17 00:00:00 2001
From: xqz <837938965@qq.com>
Date: 星期四, 03 七月 2025 10:35:06 +0800
Subject: [PATCH] 7.3 qwen

---
 smart_detecttest1111.py |  261 +++++
 qwen_ollama_detect.py   |  219 ++++
 qwen_vllm_detect.py     |  256 +++++
 qwen_ollama.py          |  332 ++++++
 qwen_vllm.py            |  246 ++++
 qwen_task.py            |  150 ++
 qwen_vllm_thread.py     |   91 +
 get_mem.py              |  318 ++++++
 int.txt                 |   33 
 vllm.py                 |   62 +
 /dev/null               |    1 
 qwen_detect.py          |  234 ++++
 detect_task1111.py      |  209 ++++
 qwen_test.py            |   36 
 conf.txt                |   14 
 b.py                    |  357 +++++++
 temp.jpg                |    0 
 a.py                    |  232 ++++
 SimSun.ttf              |    0 
 19 files changed, 3,050 insertions(+), 1 deletions(-)

diff --git a/22.txt b/22.txt
deleted file mode 100644
index 9f54fe3..0000000
--- a/22.txt
+++ /dev/null
@@ -1 +0,0 @@
-122
diff --git a/SimSun.ttf b/SimSun.ttf
new file mode 100644
index 0000000..e0115ab
--- /dev/null
+++ b/SimSun.ttf
Binary files differ
diff --git a/a.py b/a.py
new file mode 100644
index 0000000..2a88611
--- /dev/null
+++ b/a.py
@@ -0,0 +1,232 @@
+
+import threading
+import time as time_sel
+from typing import Dict
+import qwen_task
+import requests
+import os
+import torch
+import logging
+from transformers import AutoProcessor, AutoModelForVision2Seq
+from pymilvus import connections, Collection
+from logging.handlers import RotatingFileHandler
+import get_mem
+
+
+class ThreadPool:
+    def __init__(self):
+        #璇诲彇閰嶇疆鏂囦欢
+        self.config = {}
+        with open('./conf.txt', 'r', encoding='utf-8') as file:
+            for line in file:
+                # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+                line = line.strip()
+                # 璺宠繃绌鸿
+                if not line:
+                    continue
+                # 鍒嗗壊閿拰鍊�
+                if '=' in line:
+                    key, value = line.split('=', 1)
+                    # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+                    key = key.strip()
+                    value = value.strip()
+                    # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+                    self.config[key] = value
+        # 閰嶇疆鏃ュ織
+        # 纭繚鏃ュ織鐩綍瀛樺湪
+        log_dir = "logs"
+        os.makedirs(log_dir, exist_ok=True)
+        self.threads: Dict[str, threading.Thread] = {}
+        self.lock = threading.Lock()
+
+        self.device = "cuda" if torch.cuda.is_available() else "cpu"
+        # 鍒濆鍖杚wenvl妫�娴嬫ā鍨�
+        # 鎸囧畾鏈湴璺緞
+        model_path = "./Qwen2.5-VL-3B-Instruct-AWQ"
+        # 鍔犺浇妯″瀷
+        self.qwen_model = AutoModelForVision2Seq.from_pretrained(
+            model_path,
+            device_map="auto"
+        ).eval()
+        # 鍔犺浇澶勭悊鍣�
+        self.qwen_tokenizer = AutoProcessor.from_pretrained(model_path,use_fast=True)
+
+        # 鍒濆鍖朚ilvus闆嗗悎
+        connections.connect("default", host=self.config.get("milvusurl"), port=self.config.get("milvusport"))
+        # 鍔犺浇闆嗗悎
+        self.collection = Collection(name="smartobject")
+        self.collection.load()
+
+        #鏄惁鏇存柊
+        self._isupdate = False
+
+        # 鍒濆鍖栧叡浜唴瀛�
+        get_mem.smem_init()
+
+        # 閰嶇疆鏃ュ織
+        logging.basicConfig(
+            level=logging.INFO,
+            format='%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s',
+            datefmt='%Y-%m-%d %H:%M:%S',
+            handlers=[
+                # 鎸夊ぇ灏忚疆杞殑鏃ュ織鏂囦欢锛堟渶澶�10MB锛屼繚鐣�3涓浠斤級
+                RotatingFileHandler(
+                    filename=os.path.join(log_dir, 'start_log.log'),
+                    maxBytes=10 * 1024 * 1024,  # 10MB
+                    backupCount=3,
+                    encoding='utf-8'
+                ),
+                # 鍚屾椂杈撳嚭鍒版帶鍒跺彴
+                logging.StreamHandler()
+            ]
+        )
+
+    #鍚姩绾跨▼
+    def safe_start(self, target_func, camera_id):
+        """绾跨▼瀹夊叏鍚姩鏂规硶"""
+        def wrapped():
+            thread_name = threading.current_thread().name
+            try:
+                target_func(camera_id)
+            except Exception as e:
+                logging.error(f"绾跨▼寮傚父: {str(e)}", exc_info=True)
+
+        with self.lock:  # 纭繚绾跨▼瀹夊叏鍒涘缓
+            t = threading.Thread(
+                target=wrapped,
+                daemon=True  # 璁剧疆涓哄畧鎶ょ嚎绋�
+            )
+            t.start()
+            self.threads[camera_id] = t
+            return t
+
+    # 鍚姩绾跨▼浠诲姟
+    def worker(self, camera_id):
+        # 鍒濆鍖�
+        detect = qwen_task.detect_tasks()
+        detect._thread_name = f"{camera_id}"  # 璁剧疆鍚嶇О
+        detect.init_logging(f"{camera_id}")
+        # 鍒濆鍖栨娴嬫ā鍨�
+        detect.device = self.device
+        # 鍒濆鍖杚wen妯″瀷
+        detect.qwen_tokenizer = self.qwen_tokenizer
+        detect.qwen_model = self.qwen_model
+
+        # 鍒濆鍖朚ilvus闆嗗悎
+        detect.collection = self.collection
+
+        # 璁剧疆绾跨▼鍚姩鐘舵��
+        detect._running = True
+        try:
+            # 璇诲彇鍏变韩鍐呭瓨涓殑鍥剧墖
+            image_id_list = [458671636370971032]
+            for image_id in image_id_list:
+                logging.info(f"璇诲彇鍥惧儚鎴愬姛: {image_id}")
+                image_id = detect.tark_do(image_id,self.config.get("filesavepath"),self.config.get("ragurl"),self.config.get("max_tokens"))
+                logging.info(f"澶勭悊鍥惧儚鎴愬姛: {image_id}")
+        except Exception as e:
+            logging.info(f"{detect._thread_name}绾跨▼閿欒:{e}")
+
+    #璋冪敤鏄惁闇�瑕佹洿鏂�
+    def isUpdate(self):
+        try:
+            # 瀹氫箟璇锋眰鐨� URL
+            url = self.config.get("isupdateurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.get(url)
+
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                data = response.json().get("data")
+                if data.get("isChange") == 1:
+                    return True
+                else:
+                    return False
+        except Exception as e:
+            logging.info(f"璋冪敤鏄惁闇�瑕佹洿鏂版椂鍑洪敊:URL:{self.config.get('isupdateurl')}:{e}")
+            return False
+
+    #淇敼鏄惁鏇存柊鐘舵��
+    def update_status(self):
+        try:
+            # 鏇存柊鐘舵��
+            url = self.config.get("updatestatusurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.post(url)
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                return True
+            else:
+                return False
+        except Exception as e:
+            logging.info(f"淇敼鏄惁鏇存柊鐘舵�佹椂鍑洪敊:URL:{self.config.get('updatestatusurl')}:{e}")
+            return False
+
+    def shutdown_all(self) -> None:
+        """娓呯悊鎵�鏈夌嚎绋�"""
+        with self.lock:
+            for camera_id, thread in list(self.threads.items()):
+                if thread.is_alive():
+                    thread.join(timeout=1)
+                del self.threads[camera_id]
+
+    #鑾峰彇浠诲姟
+    def getTaskconf(self,isupdate):
+        try:
+            # 瀹氫箟璇锋眰鐨� URL
+            url = self.config.get("gettaskconfurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.get(url)
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                data = response.json()
+                if isupdate:
+                    # 鏇存柊鐘舵��
+                    self.update_status()
+                return data.get("data")
+            else:
+                return []
+        except Exception as e:
+            logging.info(f"璋冪敤鑾峰彇浠诲姟鏃跺嚭閿�:URL:{self.config.get('gettaskconfurl')}:{e}")
+            return []
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+    pool = ThreadPool()
+    is_init = True
+    camera_data = pool.getTaskconf(False)
+    while True:
+        try:
+            pool._isupdate = False  # 鏄惁鏇存柊鏁版嵁
+            # 鏄惁闇�瑕佹洿鏂颁换鍔℃暟鎹�
+            if pool.isUpdate():
+                # 鑾峰彇鎽勫儚鏈轰换鍔�
+                camera_data = pool.getTaskconf(True)
+                pool._isupdate = True  # 鏇存柊鏁版嵁
+
+            if is_init:
+                if camera_data:
+                    for camera in camera_data:
+                        thread = pool.threads.get(camera.get("camera_id"))
+                        if not thread:
+                            logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+                            pool.safe_start(pool.worker, camera.get('camera_id'))
+                            logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+            if pool._isupdate:
+                logging.info(f"鏇存柊绾跨▼寮�濮�")
+                pool.shutdown_all()
+                if camera_data:
+                    for camera in camera_data:
+                        thread = pool.threads.get(camera.get("camera_id"))
+                        if not thread:
+                            logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+                            pool.safe_start(pool.worker, camera.get('camera_id'))
+                            logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+                logging.info(f"鏇存柊绾跨▼缁撴潫")
+
+            is_init = False
+            time_sel.sleep(1)
+        except Exception as e:
+            logging.info(f"涓荤嚎绋嬫湭鐭ラ敊璇�:{e}")
diff --git a/b.py b/b.py
new file mode 100644
index 0000000..8e33ca6
--- /dev/null
+++ b/b.py
@@ -0,0 +1,357 @@
+
+import threading
+import time as time_sel
+from typing import Dict
+import qwen_task
+import requests
+import os
+import torch
+import logging
+from transformers import AutoProcessor, AutoModelForVision2Seq
+from pymilvus import connections, Collection
+from logging.handlers import RotatingFileHandler
+import get_mem
+
+
+class ThreadPool:
+    def __init__(self):
+        #璇诲彇閰嶇疆鏂囦欢
+        self.config = {}
+        with open('./conf.txt', 'r', encoding='utf-8') as file:
+            for line in file:
+                # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+                line = line.strip()
+                # 璺宠繃绌鸿
+                if not line:
+                    continue
+                # 鍒嗗壊閿拰鍊�
+                if '=' in line:
+                    key, value = line.split('=', 1)
+                    # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+                    key = key.strip()
+                    value = value.strip()
+                    # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+                    self.config[key] = value
+        # 閰嶇疆鏃ュ織
+        # 纭繚鏃ュ織鐩綍瀛樺湪
+        log_dir = "logs"
+        os.makedirs(log_dir, exist_ok=True)
+        self.threads: Dict[str, threading.Thread] = {}
+        self.lock = threading.Lock()
+
+        self.device = "cuda" if torch.cuda.is_available() else "cpu"
+        # 鍒濆鍖杚wenvl妫�娴嬫ā鍨�
+        # 鎸囧畾鏈湴璺緞
+        model_path = "./Qwen2-VL-2B-Instruct"
+        # 鍔犺浇妯″瀷
+        self.qwen_model = AutoModelForVision2Seq.from_pretrained(
+            model_path,
+            device_map="auto",  # 鑷姩鍒嗛厤GPU
+            torch_dtype=torch.float16,  # 鍗婄簿搴﹁妭鐪佹樉瀛�
+            trust_remote_code=True  # 鍏佽鎵ц鑷畾涔変唬鐮�
+        ).eval()
+        # 鍔犺浇澶勭悊鍣�
+        self.qwen_tokenizer = AutoProcessor.from_pretrained(model_path)
+
+        # 鍒濆鍖朚ilvus闆嗗悎
+        connections.connect("default", host=self.config.get("milvusurl"), port=self.config.get("milvusport"))
+        # 鍔犺浇闆嗗悎
+        self.collection = Collection(name="smartobject")
+        self.collection.load()
+
+        #鏄惁鏇存柊
+        self._isupdate = False
+
+        # 鍒濆鍖栧叡浜唴瀛�
+        get_mem.smem_init()
+
+        # 閰嶇疆鏃ュ織
+        logging.basicConfig(
+            level=logging.INFO,
+            format='%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s',
+            datefmt='%Y-%m-%d %H:%M:%S',
+            handlers=[
+                # 鎸夊ぇ灏忚疆杞殑鏃ュ織鏂囦欢锛堟渶澶�10MB锛屼繚鐣�3涓浠斤級
+                RotatingFileHandler(
+                    filename=os.path.join(log_dir, 'start_log.log'),
+                    maxBytes=10 * 1024 * 1024,  # 10MB
+                    backupCount=3,
+                    encoding='utf-8'
+                ),
+                # 鍚屾椂杈撳嚭鍒版帶鍒跺彴
+                logging.StreamHandler()
+            ]
+        )
+
+    #鍚姩绾跨▼
+    def safe_start(self, target_func, camera_id):
+        """绾跨▼瀹夊叏鍚姩鏂规硶"""
+        def wrapped():
+            thread_name = threading.current_thread().name
+            try:
+                target_func(camera_id)
+            except Exception as e:
+                logging.error(f"绾跨▼寮傚父: {str(e)}", exc_info=True)
+
+        with self.lock:  # 纭繚绾跨▼瀹夊叏鍒涘缓
+            t = threading.Thread(
+                target=wrapped,
+                daemon=True  # 璁剧疆涓哄畧鎶ょ嚎绋�
+            )
+            t.start()
+            self.threads[camera_id] = t
+            return t
+
+    # 鍚姩绾跨▼浠诲姟
+    def worker(self, camera_id):
+        # 鍒濆鍖�
+        detect = qwen_task.detect_tasks()
+        detect._thread_name = f"{camera_id}"  # 璁剧疆鍚嶇О
+        detect.init_logging(f"{camera_id}")
+        # 鍒濆鍖栨娴嬫ā鍨�
+        detect.device = self.device
+        # 鍒濆鍖杚wen妯″瀷
+        detect.qwen_tokenizer = self.qwen_tokenizer
+        detect.qwen_model = self.qwen_model
+
+        # 鍒濆鍖朚ilvus闆嗗悎
+        detect.collection = self.collection
+
+        # 璁剧疆绾跨▼鍚姩鐘舵��
+        detect._running = True
+        try:
+            # 璇诲彇鍏变韩鍐呭瓨涓殑鍥剧墖
+            image_id_list = [458450378519380938,
+458450378519380940,
+458450378519380942,
+458450378519380944,
+458450378519380946,
+458450378519380948,
+458450378519380950,
+458450378519380952,
+458450378519380954,
+458450378519380956,
+458450378519380958,
+458450378519380960,
+458450378519380962,
+458450378519380964,
+0,
+458450378519380966,
+458450378519380968,
+0,
+458450378519380970,
+458450378519380972,
+458450378519380974,
+458450378519380976,
+458450378519380978,
+458450378519380980,
+458450378519380982,
+458450378519380984,
+458450378519380986,
+458450378519380988,
+458450378519380990,
+458450378519380992,
+0,
+458450378519380994,
+458450378519380996,
+0,
+458450378519380998,
+458450378519381000,
+0,
+458450378519381002,
+458450378519381004,
+458450378519381006,
+0,
+458450378519381008,
+458450378519381010,
+458450378519381012,
+458450378519381014,
+458450378519381016,
+458450378519381018,
+458450378519381020,
+458450378519381022,
+458450378519381024,
+458450378519381026,
+458450378519381028,
+458450378519381030,
+458450378519381032,
+458450378519381034,
+458450378519381036,
+458450378519381038,
+458450378519381040,
+458450378519381042,
+458450378519381044,
+458450378519381046,
+0,
+458450378519381048,
+458450378519381050,
+458450378519381052,
+458450378519381054,
+458450378519381056,
+458450378519381058,
+458450378519381060,
+458450378519381062,
+458450378519381064,
+458450378519381066,
+458450378519381068,
+458450378519381070,
+458450378519381072,
+458450378519381074,
+458450378519381076,
+458450378519381078,
+458450378519381080,
+458450378519381082,
+458450378519381084,
+0,
+458450378519381086,
+458450378519381088,
+458450378519381090,
+458450378519381092,
+458450378519381094,
+458450378519381096,
+458450378519381098,
+458450378519381100,
+458450378519381102,
+458450378519381104,
+458450378519381106,
+458450378519381108,
+458450378519381110,
+458450378519381112,
+458450378519381114,
+458450378519381116,
+458450378519381118,
+458450378519381120,
+458450378519381122,
+458450378519381124,
+458450378519381126,
+0,
+458450378519381128,
+458450378519381130,
+458450378519381132,
+458450378519381134,
+458450378519381136,
+458450378519381138,
+458450378519381140,
+458450378519381142,
+458450378519381144,
+458450378519381146,
+458450378519381148,
+458450378519381150,
+458450378519381152,
+458450378519381154,
+458450378519381156,
+458450378519381158
+]
+
+
+
+            for image_id in image_id_list:
+                logging.info(f"璇诲彇鍥惧儚鎴愬姛: {image_id}")
+                image_id = detect.tark_do(image_id,self.config.get("filesavepath"),self.config.get("ragurl"),self.config.get("max_tokens"))
+                logging.info(f"澶勭悊鍥惧儚鎴愬姛: {image_id}")
+        except Exception as e:
+            logging.info(f"{detect._thread_name}绾跨▼閿欒:{e}")
+
+    #璋冪敤鏄惁闇�瑕佹洿鏂�
+    def isUpdate(self):
+        try:
+            # 瀹氫箟璇锋眰鐨� URL
+            url = self.config.get("isupdateurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.get(url)
+
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                data = response.json().get("data")
+                if data.get("isChange") == 1:
+                    return True
+                else:
+                    return False
+        except Exception as e:
+            logging.info(f"璋冪敤鏄惁闇�瑕佹洿鏂版椂鍑洪敊:URL:{self.config.get('isupdateurl')}:{e}")
+            return False
+
+    #淇敼鏄惁鏇存柊鐘舵��
+    def update_status(self):
+        try:
+            # 鏇存柊鐘舵��
+            url = self.config.get("updatestatusurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.post(url)
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                return True
+            else:
+                return False
+        except Exception as e:
+            logging.info(f"淇敼鏄惁鏇存柊鐘舵�佹椂鍑洪敊:URL:{self.config.get('updatestatusurl')}:{e}")
+            return False
+
+    def shutdown_all(self) -> None:
+        """娓呯悊鎵�鏈夌嚎绋�"""
+        with self.lock:
+            for camera_id, thread in list(self.threads.items()):
+                if thread.is_alive():
+                    thread.join(timeout=1)
+                del self.threads[camera_id]
+
+    #鑾峰彇浠诲姟
+    def getTaskconf(self,isupdate):
+        try:
+            # 瀹氫箟璇锋眰鐨� URL
+            url = self.config.get("gettaskconfurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.get(url)
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                data = response.json()
+                if isupdate:
+                    # 鏇存柊鐘舵��
+                    self.update_status()
+                return data.get("data")
+            else:
+                return []
+        except Exception as e:
+            logging.info(f"璋冪敤鑾峰彇浠诲姟鏃跺嚭閿�:URL:{self.config.get('gettaskconfurl')}:{e}")
+            return []
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+    pool = ThreadPool()
+    is_init = True
+    camera_data = pool.getTaskconf(False)
+    while True:
+        try:
+            pool._isupdate = False  # 鏄惁鏇存柊鏁版嵁
+            # 鏄惁闇�瑕佹洿鏂颁换鍔℃暟鎹�
+            if pool.isUpdate():
+                # 鑾峰彇鎽勫儚鏈轰换鍔�
+                camera_data = pool.getTaskconf(True)
+                pool._isupdate = True  # 鏇存柊鏁版嵁
+
+            if is_init:
+                if camera_data:
+                    for camera in camera_data:
+                        thread = pool.threads.get(camera.get("camera_id"))
+                        if not thread:
+                            logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+                            pool.safe_start(pool.worker, camera.get('camera_id'))
+                            logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+            if pool._isupdate:
+                logging.info(f"鏇存柊绾跨▼寮�濮�")
+                pool.shutdown_all()
+                if camera_data:
+                    for camera in camera_data:
+                        thread = pool.threads.get(camera.get("camera_id"))
+                        if not thread:
+                            logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+                            pool.safe_start(pool.worker, camera.get('camera_id'))
+                            logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+                logging.info(f"鏇存柊绾跨▼缁撴潫")
+
+            is_init = False
+            time_sel.sleep(1)
+        except Exception as e:
+            logging.info(f"涓荤嚎绋嬫湭鐭ラ敊璇�:{e}")
diff --git a/conf.txt b/conf.txt
new file mode 100644
index 0000000..4d67331
--- /dev/null
+++ b/conf.txt
@@ -0,0 +1,14 @@
+milvusurl = 192.168.1.232
+milvusport = 19530
+isupdateurl = http://192.168.1.232:8088/v1/task/isChange?stateType=2
+gettaskconfurl = http://192.168.1.232:8088/v1/task/getTaskConf
+updatestatusurl = http://192.168.1.232:8088/v1/task/updateChangeStatus?stateType=2
+videotaskurl = http://192.168.1.232:8089/api/v1/camera/record/task
+ragurl=http://192.168.1.232:8870
+ragmode=qwen2.5vl
+ollamaurl=http://192.168.1.232:11434
+ollamamode=qwen2.5vl
+filesavepath = /opt/smart
+max_tokens = 2000
+threadnum = 10
+
diff --git a/detect_task1111.py b/detect_task1111.py
new file mode 100644
index 0000000..b5462f8
--- /dev/null
+++ b/detect_task1111.py
@@ -0,0 +1,209 @@
+import os
+import logging
+from logging.handlers import RotatingFileHandler
+
+import cv2
+import torch
+from PIL import Image
+from pymilvus import connections, Collection
+from transformers import AutoTokenizer, AutoModelForVision2Seq, AutoProcessor, BitsAndBytesConfig
+from flask import Flask, request, jsonify
+
+app = Flask(__name__)
+#瑙勫垯姣斿
+def cross_collection_vector_compare(self,image_id,video_point_id,rule_id,video_image_time,frame_id,task_id,video_path,videotaskurl):
+    try:
+        # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+        res_a = self.collection.query(
+            expr=f"id in {image_id}",
+            output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "object_label", "task_id", "event_level_id",
+                           "video_point_id", "detect_num", "detect_id", "detect_time", "image_path", "video_path"],
+            consistency_level="Strong"
+        )
+
+        # 2. 浠庨泦鍚圔鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+        res_b = self.collection_rule.query(
+            expr=f"rule_id in {rule_id}",
+            output_fields=["id", "zh_desc_class", "text_vector","range_value"],
+            consistency_level="Strong"
+        )
+
+        # 3. 璁$畻涓や袱鐩镐技搴�
+        results = []
+        pos_weights = {
+            ('n', 'n'): 1.0,  # 鍚嶈瘝鍖归厤
+            ('v', 'v'): 0.8,  # 鍔ㄨ瘝鍖归厤
+            ('n', 'v'): 0.3  # 鍚嶈瘝-鍔ㄨ瘝浜ゅ弶
+        }
+        # 寰幆缁撴灉闆�
+        for item_a in res_a:
+            if item_a["detect_num"]>0 : # 鏈夋娴嬪埌鐩爣鏃惰繘琛屾瘮瀵�
+                for item_b in res_b: # 鍜屾瘡涓鍒欓」杩涜瀵规瘮
+                    similarity = 0
+                    # 1. 鍚戦噺鐩镐技搴︼紙60%鏉冮噸锛�
+                    # 灏嗗悜閲忚浆涓簄umpy鏁扮粍
+                    vec_a = np.array(item_a["text_vector"])
+                    vec_b = np.array(item_b["text_vector"])
+                    assert vec_a.shape == vec_b.shape, f"缁村害涓嶅尮閰�: {vec_a.shape} vs {vec_b.shape}"
+                    vec_a = vec_a.astype(np.float64)  # 鎻愬崌璁$畻绮惧害
+                    vec_b = vec_b.astype(np.float64)
+                    # 璁$畻鐩镐技搴�
+                    vector_sim = np.dot(vec_a, vec_b) / (np.linalg.norm(vec_a) * np.linalg.norm(vec_b))
+
+                    # 2. 璇嶆�у尮閰嶅害锛�40%鏉冮噸锛�
+                    desc_a = ast.literal_eval(item_a['zh_desc_class'])  # 鑾峰彇鐩爣璇箟
+                    desc_b = ast.literal_eval(item_b['zh_desc_class'])
+                    for clas_a in desc_a:   # 鍜屾瘡涓洰鏍囪涔夎繘琛屽姣�
+                        pos_match = 0
+                        for (_, pos_a, _), (_, pos_b, _) in zip(clas_a, desc_b):
+                            pos_match += pos_weights.get((pos_a, pos_b), 0)
+                        pos_match /= max(len(clas_a), len(desc_b))
+
+                        #鎸夋潈閲嶇粍瑁� 褰撳墠鐩镐技搴� 骞惰祴鍊兼渶澶у��
+                        stem_int = 0.6 * vector_sim + 0.4 * pos_match
+                        if stem_int > similarity:
+                            similarity = stem_int
+
+                    # 3.鐩镐技搴﹀鏋滃ぇ浜庤鍒欏尮閰嶉槇鍊�,缁勮棰勮鏁版嵁
+                    if similarity > item_b["range_value"]:
+                        logging.info(f"鐩镐技搴︼細{similarity}锛歿item_a['zh_desc_class']} {item_b['zh_desc_class']}")
+                        results.append({
+                            "a_id": item_a["id"],
+                            "b_id": item_b["id"],
+                            "similarity": round(float(similarity), 4)
+                        })
+
+        # 4. 鎸夌浉浼煎害鎺掑簭
+        if len(results) > 0:
+            comparison_results = sorted(results, key=lambda x: x["similarity"], reverse=True) # 闆嗗悎鎺掑簭
+            # 淇濆瓨褰曞儚瑙嗛
+            asyncio.run(self.video_task(video_point_id,video_image_time,"basic",frame_id,video_path,videotaskurl))
+            # 淇濆瓨鍒癿ilvus
+            self.update_milvus(image_id,res_a,1,comparison_results[0]['similarity'],rule_id)
+        else:
+            self.update_milvus(image_id,res_a,0,0.0,rule_id)
+    except Exception as e:
+        self.logger.info(f"{video_point_id}绾跨▼锛氳鍒欏姣旀椂鍑洪敊:{image_id,rule_id}锛� {e}")
+
+#鍚姩褰曞儚
+async def video_task(self,video_point_id,video_image_time,task_id,frame_id,video_path,videotaskurl):
+    try:
+        json_data = {
+            "cameraId": f"{video_point_id}",
+            "timestamp": video_image_time,
+            "preSeconds": 10,
+            "postSeconds": 10,
+            "taskId": task_id,
+            "fid": frame_id,
+            "uploadUrl": video_path,
+            "uploadType": "local"
+        }
+        self.logger.info(f"{video_point_id}绾跨▼锛氳皟鐢ㄥ綍鍍忔湇鍔�:{videotaskurl, json_data}")
+
+        # 瀹氫箟璇锋眰鐨� URL
+        # 鍙戦�� GET 璇锋眰
+        response = requests.post(videotaskurl,json=json_data,timeout=(0.03, 0.03))
+        # 妫�鏌ュ搷搴旂姸鎬佺爜
+        if response.status_code == 200:
+            data = response.json()
+            print(data)
+    except Exception as e:
+        self.logger.info(f"{self._thread_name}绾跨▼锛氳皟鐢ㄥ綍鍍忔椂鍑洪敊:鍦板潃锛歿videotaskurl}锛歿e}")
+
+def update_milvus(self,image_id,res_a,is_waning,similarity,rule_id_list):
+    try:
+        # 淇濆瓨鍒癿ilvus
+        self.collection.upsert(
+            data=[{
+                "id": image_id[0],
+                "text_vector": res_a[0]["text_vector"],
+                "is_waning": is_waning,
+                "waning_value": similarity,
+                "rule_id": rule_id_list,
+                "zh_desc_class": res_a[0]['zh_desc_class'],  # text_vector
+                "bounding_box": res_a[0]['bounding_box'],  # bounding_box
+                "object_label": res_a[0]['object_label'],  # desc
+                "task_id": res_a[0]['task_id'],  # task_id
+                "event_level_id": res_a[0]['event_level_id'],  # event_level_id
+                "video_point_id": res_a[0]['video_point_id'],  # video_point_id
+                "detect_num": res_a[0]['detect_num'],
+                "detect_id": res_a[0]['detect_id'],  # detect_id
+                "detect_time": res_a[0]['detect_time'],  # detect_time
+                "image_path": res_a[0]['image_path'],  # image_path
+                "video_path": res_a[0]['video_path']  # video_path
+            }]
+        )
+    except Exception as e:
+        self.logger.info(f"{self._thread_name}绾跨▼锛氳鍒欏姣斿悗淇敼鏁版嵁鏃跺嚭閿�:{image_id}锛氭槸鍚﹂璀is_waning}锛氶璀﹀�硷細{similarity}锛氳鍒檌d:{rule_id_list}:鏁版嵁闆嗗悎锛歿len(res_a)} :{e}")
+
+def tark_do(image_id,image_path,milvusurl,milvusport):
+    try :
+        # 鍒濆鍖杚wenvl妫�娴嬫ā鍨�
+        qwen_tokenizer = AutoProcessor.from_pretrained("Qwen2-VL-2B", trust_remote_code=True)
+        qwen_model = AutoModelForVision2Seq.from_pretrained("Qwen2-VL-2B",  device_map="auto", trust_remote_code=True).eval()
+
+        # 鍒濆鍖朚ilvus闆嗗悎
+        connections.connect("default", host=milvusurl, port=milvusport)
+        # 鍔犺浇闆嗗悎
+        collection = Collection(name="smartobject")
+        collection.load()
+        # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+        res_a = collection.query(
+            expr=f"id == {image_id}",
+            output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "object_label", "task_id", "event_level_id",
+                           "video_point_id", "detect_num", "is_waning", "waning_value",  "rule_id", "detect_id", "detect_time", "image_path", "video_path"],
+            consistency_level="Strong"
+        )
+        # 鍥剧墖鍜岃棰戝湴鍧�
+        image = Image.open(image_path)  # 鏇挎崲涓烘偍鐨勫浘鐗囪矾寰�
+        image = image.thumbnail((512, 512))
+        text = "鎻忚堪杩欏紶鍥剧墖鐨勫唴瀹�"
+        # 澶勭悊杈撳叆
+        inputs = qwen_tokenizer(text=text, images=image, return_tensors="pt").to("cuda")
+        # 鐢熸垚杈撳嚭
+        with torch.no_grad():
+            outputs = qwen_model.generate(**inputs, max_new_tokens=50)
+        response = qwen_tokenizer.decode(outputs[0], skip_special_tokens=True)
+        print(response)
+
+        # 淇濆瓨鍒癿ilvus
+        collection.upsert(
+            data=[{
+                "id": image_id,
+                "text_vector": res_a[0]["text_vector"],
+                "is_waning": res_a[0]["is_waning"],
+                "waning_value": res_a[0]["waning_value"],
+                "rule_id": res_a[0]["rule_id"],
+                "zh_desc_class": res_a[0]['zh_desc_class'],  # text_vector
+                "bounding_box": res_a[0]['bounding_box'],  # bounding_box
+                "object_label": f"{response}",  # desc
+                "task_id": res_a[0]['task_id'],  # task_id
+                "event_level_id": res_a[0]['event_level_id'],  # event_level_id
+                "video_point_id": res_a[0]['video_point_id'],  # video_point_id
+                "detect_num": res_a[0]['detect_num'],
+                "detect_id": res_a[0]['detect_id'],  # detect_id
+                "detect_time": res_a[0]['detect_time'],  # detect_time
+                "image_path": res_a[0]['image_path'],  # image_path
+                "video_path": res_a[0]['video_path']  # video_path
+            }]
+        )
+        print(f"鎵ц浠诲姟{image_id,image_path}锛氱粨鏉�")
+        return 1
+    except Exception as e:
+        print(f"鎵ц妯″瀷瑙f瀽鏃跺嚭閿�:{image_id,image_path} :{e}")
+        return 0
+
+
+# 绀轰緥锛氭枃鏈鐞嗘帴鍙�
+@app.route('/process', methods=['POST'])
+def process_text():
+    data = request.json
+    # 璋冪敤鎮ㄧ殑澶勭悊鍑芥暟锛堜緥濡� Qwen2-VL 妯″瀷锛�
+    try:
+        return tark_do(data.get("image_id"),data.get("image_path"),data.get("milvusurl"),data.get("milvusport"))  # 鏇挎崲涓哄疄闄呭嚱鏁�
+    except Exception as e:
+        # 閿欒澶勭悊
+        return 0
+
+if __name__ == '__main__':
+    app.run(host='0.0.0.0', port=5000, debug=True)
\ No newline at end of file
diff --git a/get_mem.py b/get_mem.py
new file mode 100644
index 0000000..75752d2
--- /dev/null
+++ b/get_mem.py
@@ -0,0 +1,318 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+SMEM Python鎺ュ彛妯″潡
+鎻愪緵瀵瑰叡浜唴瀛樺簱鐨勮闂紝鐢ㄤ簬璇诲彇鎽勫儚澶村浘鍍忓拰鍚戦噺鏁版嵁
+"""
+
+import os
+import sys
+import ctypes
+from ctypes import *
+from typing import Tuple, List, Dict, Optional, Any
+
+# 瀹氫箟閿欒鐮佸父閲�
+SMEM_SUCCESS = 0
+SMEM_ERROR_INVALID_PARAM = -1
+SMEM_ERROR_CONFIG = -2
+SMEM_ERROR_CREATE_SHM = -3
+SMEM_ERROR_NO_MEMORY = -4
+SMEM_ERROR_BUSY = -5
+SMEM_ERROR_NOT_FOUND_CAMERID = -6
+SMEM_ERROR_NOT_FOUND_FRAMEID = -7
+SMEM_ERROR_INVALID_STATE = -8
+SMEM_ERROR_INVALID_SIZE = -9
+
+
+# 瀹氫箟鍘熷瓙绫诲瀷
+class atomic_size_t(Structure):
+    _fields_ = [("__a", c_size_t)]
+
+
+class atomic_int(Structure):
+    _fields_ = [("__a", c_int)]
+
+
+# 淇ActiveCameraList缁撴瀯浣撳畾涔�
+class ActiveCameraList(Structure):
+    _fields_ = [
+        ("camera_ids_offset", c_size_t),  # 鎽勫儚澶碔D鏁扮粍鐩稿鍋忕Щ閲�
+        ("count", atomic_size_t),  # 褰撳墠娲诲姩鎽勫儚澶存暟閲�
+        ("capacity", atomic_size_t),  # 鏁扮粍瀹归噺
+        ("lock", atomic_int)  # 鐢ㄤ簬鍚屾鐨勯攣
+    ]
+
+
+# 淇ReadImageData缁撴瀯浣撳畾涔�
+class ReadImageData(Structure):
+    _fields_ = [
+        ("frame_id", c_uint64),
+        ("clock_time", c_uint64),
+        ("image_size", c_size_t),
+        ("image_data", POINTER(c_char))
+    ]
+
+
+# 鍔犺浇鍏变韩搴�
+def load_smem_library():
+    """鍔犺浇鍏变韩鍐呭瓨搴�"""
+    try:
+        # 灏濊瘯浠庝笉鍚屼綅缃姞杞藉簱
+        lib_paths = [
+            "./libsmem.so",  # 褰撳墠鐩綍
+            "/lib/x86_64-linux-gnu/libsmem.so",  # 绯荤粺搴撶洰褰�
+            os.path.join(os.path.dirname(os.path.abspath(__file__)), "libsmem.so")  # 妯″潡鐩綍
+        ]
+
+        for path in lib_paths:
+            if os.path.exists(path):
+                return CDLL(path)
+
+        # 濡傛灉鎵句笉鍒版寚瀹氳矾寰勶紝灏濊瘯鐩存帴鎸夊悕绉板姞杞�
+        return CDLL("libsmem.so")
+    except Exception as e:
+        print(f"鍔犺浇鍏变韩鍐呭瓨搴撳け璐�: {e}")
+        sys.exit(1)
+
+
+# 鍔犺浇搴�
+_lib = load_smem_library()
+
+# 璁剧疆鍑芥暟鍘熷瀷
+_lib.smem_init.argtypes = []
+_lib.smem_init.restype = c_int
+
+_lib.client_smem_init.argtypes = []
+_lib.client_smem_init.restype = c_int
+
+_lib.smem_destroy.argtypes = []
+_lib.smem_destroy.restype = None
+
+_lib.offset_to_ptr.argtypes = [c_size_t]
+_lib.offset_to_ptr.restype = c_void_p
+
+_lib.smem_get_camera_list.argtypes = []
+_lib.smem_get_camera_list.restype = POINTER(ActiveCameraList)
+
+# dino璇诲彇 鎽勫儚澶磇d
+_lib.smem_read_frame_dino.argtypes = [c_int64, POINTER(ReadImageData)]
+_lib.smem_read_frame_dino.restype = c_int
+
+# dino璁剧疆鍗冮棶id
+_lib.smem_set_qianwenID.argtypes = [c_int64, c_uint64, c_uint64]
+_lib.smem_set_qianwenID.restype = c_int
+
+# 鍗冮棶璇诲彇
+_lib.smem_read_frame_qianwen.argtypes = [c_int64]
+_lib.smem_read_frame_qianwen.restype = c_uint64
+
+_lib.smem_destory_frame.argtypes = [c_int64, c_uint64]
+_lib.smem_destory_frame.restype = c_int
+
+
+# Python鍖呰鍑芥暟
+def smem_init() -> int:
+    return _lib.client_smem_init()
+
+
+def get_active_cameras() -> List[int]:
+    """
+    鑾峰彇娲诲姩鎽勫儚澶村垪琛�
+
+    Returns:
+        List[int]: 杩斿洖鎽勫儚澶碔D鍒楄〃锛屽鏋滃彂鐢熼敊璇垯杩斿洖绌哄垪琛�
+    """
+    try:
+        # 鑾峰彇鎽勫儚澶村垪琛ㄦ寚閽�
+        camera_list_ptr = _lib.smem_get_camera_list()
+        if not camera_list_ptr:
+            print("閿欒锛歴mem_get_camera_list杩斿洖绌烘寚閽�")
+            return []
+
+        # 瀹夊叏鍦拌闂粨鏋勪綋鍐呭
+        try:
+            camera_list = camera_list_ptr.contents
+        except (ValueError, AttributeError) as e:
+            print(f"閿欒锛氭棤娉曡闂憚鍍忓ご鍒楄〃鍐呭: {e}")
+            return []
+
+        # 鑾峰彇鎽勫儚澶存暟閲�
+        try:
+            count = camera_list.count.__a
+            if count < 0 or count > 1000:  # 璺宠繃鏃犳晥鏁伴噺
+                print(f"閿欒锛氭棤鏁堢殑鎽勫儚澶存暟閲�: {count}")
+                return []
+        except AttributeError as e:
+            print(f"閿欒锛氭棤娉曡闂甤ount瀛楁: {e}")
+            return []
+
+        # 鑾峰彇camera_ids鏁扮粍鎸囬拡
+        camera_ids_ptr = _lib.offset_to_ptr(camera_list.camera_ids_offset)
+        if not camera_ids_ptr:
+            print("閿欒锛氭棤娉曡幏鍙朿amera_ids鏁扮粍鎸囬拡")
+            return []
+
+        # 杞崲涓篜ython鍒楄〃
+        camera_ids = cast(camera_ids_ptr, POINTER(c_int64))
+        result = []
+        for i in range(count):
+            try:
+                camera_id = camera_ids[i]
+                if camera_id != -1:  # 璺宠繃鏃犳晥ID
+                    result.append(camera_id)
+            except (IndexError, ValueError) as e:
+                print(f"璀﹀憡锛氳闂储寮晎i}鏃跺嚭閿�: {e}")
+                continue
+
+        return result
+
+    except Exception as e:
+        print(f"閿欒锛氳幏鍙栨憚鍍忓ご鍒楄〃鏃跺彂鐢熷紓甯�: {e}")
+        return []
+
+
+def smem_read_frame_image_dino(camera_id: int) -> Tuple[int, Dict[str, Any]]:
+    """
+    璇诲彇鎸囧畾鎽勫儚澶寸殑鏈�灏忓抚鍙峰浘鍍忔暟鎹�
+
+    Args:
+        camera_id: 鎽勫儚澶碔D
+
+    Returns:
+        (鐘舵�佺爜, 鍥惧儚鏁版嵁瀛楀吀)
+    """
+    # 鍒涘缓杈撳嚭缁撴瀯浣�
+    read_data = ReadImageData()
+
+    # 璋冪敤C鍑芥暟
+    status = _lib.smem_read_frame_dino(camera_id, byref(read_data))
+
+    # 澶勭悊缁撴灉
+    if status == SMEM_SUCCESS:
+        # 鍙鍒跺疄闄呬娇鐢ㄧ殑鏁版嵁閮ㄥ垎
+        actual_data = bytes(read_data.image_data[:read_data.image_size])
+        result = {
+            "frame_id": read_data.frame_id,
+            "clock_time": read_data.clock_time,
+            "image_size": read_data.image_size,
+            "image_data": actual_data
+        }
+    else:
+        result = {
+            "error": f"璇诲彇澶辫触锛岄敊璇爜: {status}"
+        }
+
+    return status, result
+
+
+def smem_set_qianwen_id(camera_id: int, frame_Id: int, qianwen_id: int) -> int:
+    """
+    璁剧疆鎸囧畾鎽勫儚澶寸殑鍗冮棶ID
+
+    Args:
+        camera_id: 鎽勫儚澶碔D
+        frame_id: 甯d
+        qianwenID: 鍗冮棶id
+    Returns:
+        鐘舵�佺爜
+    """
+    return _lib.smem_set_qianwenID(camera_id, frame_Id, qianwen_id)
+
+
+def smem_read_frame_qianwen(camera_id: int) -> int:
+    """
+    璇诲彇鎸囧畾鎽勫儚澶寸殑鍗冮棶ID
+
+    Args:
+        camera_id: 鎽勫儚澶碔D
+
+    Returns:
+        鎴愬姛鏃惰繑鍥炲崈闂甀D锛堥潪璐熷�硷級锛屽け璐ユ椂杩斿洖閿欒鐮侊紙璐熷�硷級
+    """
+    # 璋冪敤C鍑芥暟锛岃繑鍥炲�煎皬浜�0琛ㄧず閿欒锛屽ぇ浜庣瓑浜�0琛ㄧず鎴愬姛骞朵笖璇ュ�煎氨鏄痲ianwenID
+    result = _lib.smem_read_frame_qianwen(camera_id)
+    return result
+
+
+def smem_destory_frame_image(camera_id: int, frame_id: int) -> int:
+    """
+    閿�姣佹寚瀹氭憚鍍忓ご鐨勬寚瀹氬抚鍙峰浘鍍忔暟鎹�
+
+    Args:
+        camera_id: 鎽勫儚澶碔D
+        frame_id: 甯у彿
+
+    Returns:
+        鐘舵�佺爜
+    """
+    return _lib.smem_destory_frame(camera_id, frame_id)
+
+
+# 閿欒鐮佽浆鎹负鍙瀛楃涓�
+def smem_error_to_string(error_code: int) -> str:
+    """
+    灏嗛敊璇爜杞崲涓哄彲璇诲瓧绗︿覆
+
+    Args:
+        error_code: 閿欒鐮�
+
+    Returns:
+        閿欒鎻忚堪瀛楃涓�
+    """
+    error_map = {
+        SMEM_SUCCESS: "鎴愬姛",
+        SMEM_ERROR_INVALID_PARAM: "鏃犳晥鍙傛暟",
+        SMEM_ERROR_CONFIG: "閰嶇疆閿欒",
+        SMEM_ERROR_CREATE_SHM: "鍒涘缓鍏变韩鍐呭瓨澶辫触",
+        SMEM_ERROR_NO_MEMORY: "鍐呭瓨涓嶈冻",
+        SMEM_ERROR_BUSY: "璧勬簮蹇�",
+        SMEM_ERROR_NOT_FOUND_CAMERID: "鏈壘鍒版憚鍍忓ご",
+        SMEM_ERROR_NOT_FOUND_FRAMEID: "鏈壘鍒板抚鍙�",
+        SMEM_ERROR_INVALID_STATE: "鏃犳晥鐘舵��",
+        SMEM_ERROR_INVALID_SIZE: "鏃犳晥澶у皬"
+    }
+    return error_map.get(error_code, f"鏈煡閿欒 ({error_code})")
+
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+    # 鍒濆鍖栧叡浜唴瀛�
+    status = smem_init()
+    if status != SMEM_SUCCESS:
+        print(f"python---鍒濆鍖栧け璐�: {smem_error_to_string(status)}")
+        sys.exit(1)
+
+    print("python---鍒濆鍖栨垚鍔�")
+
+    try:
+        # 鑾峰彇鎽勫儚澶村垪琛�
+        camera_list = get_active_cameras()
+        print(f"python---鍙戠幇 {len(camera_list)} 涓椿鍔ㄦ憚鍍忓ご")
+
+        for camera_id in camera_list:
+            # print(f"鎽勫儚澶碔D: {camera_id}")
+
+            # 璇诲彇鍥惧儚鏁版嵁
+            status, image_data = smem_read_frame_image_dino(camera_id)
+            if status == SMEM_SUCCESS:
+                image_size = image_data["image_size"]
+                print(f"  python---dino---------------------璇诲彇鎴愬姛:")
+                print(f"  python---dino--甯у彿: {image_data['frame_id']}")
+                print(f"  python---dino--澶у皬: {image_data['image_size']} 瀛楄妭")
+                print(f"  python---dino--鏃堕棿鎴�: {image_data['clock_time']}")
+                # print(f"  dino--鏁版嵁: {image_data['image_data']}")
+                qianwenID = camera_id * 10 + 111
+                aframdid = image_data["frame_id"]
+                print(f"  python---璁剧疆褰撳墠 鍗冮棶 ID: {qianwenID}   褰撳墠甯ф槸ID:  {aframdid} ,鍗冮棶璇诲彇..")
+                smem_set_qianwen_id(camera_id, aframdid, qianwenID)
+                status1 = smem_read_frame_qianwen(camera_id)
+                if status1 > 0:
+                    print(f"  python---qianwen----------------------璇诲彇鎴愬姛:")
+                    print(f"  python---qianwen--鍗冮棶ID: {status1}")
+                else:
+                    print(f"python---qianwen璇诲彇澶辫触: {smem_error_to_string(status1)}")
+            else:
+                print(f"python---璇诲彇鍥惧儚澶辫触: {smem_error_to_string(status)}")
+
+    finally:
+        print("python---鎿嶄綔瀹屾垚")
\ No newline at end of file
diff --git a/int.txt b/int.txt
new file mode 100644
index 0000000..2929776
--- /dev/null
+++ b/int.txt
@@ -0,0 +1,33 @@
+pip install numpy==1.26.4 timm==0.6.13 ninja pymilvus supervision jieba sentencepiece peft==0.7.1 auto-gptq accelerate transformers_stream_generator tiktoken  einops  optimum
+pip install torch==2.1.2+cu118 torchvision==0.16.2+cu118 --index-url https://download.pytorch.org/whl/cu118
+pip install transformers==4.51.0 bitsandbytes==0.44.0 accelerate==0.27.0
+
+
+[Unit]
+Description= dinoapp
+After=network.target
+
+
+[Service]
+User=root
+Group=root
+Environment="PATH=/root/anaconda3/envs/smartenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+ExecStart=/root/anaconda3/envs/smartenv/bin/python /home/basic/dino/dinostart.py
+WorkingDirectory=/home/basic/dino
+
+Restart=always
+RestartSec=10
+StandardOutput=syslog
+StandardError=syslog
+
+[Install]
+WantedBy=multi-user.target
+
+# 閲嶆柊鍔犺浇Systemd閰嶇疆
+sudo systemctl daemon-reload
+
+# 鍚敤寮�鏈鸿嚜鍚�
+sudo systemctl enable my_python_app.service
+
+# 绔嬪嵆鍚姩鏈嶅姟
+sudo systemctl start my_python_app.service
\ No newline at end of file
diff --git a/qwen_detect.py b/qwen_detect.py
new file mode 100644
index 0000000..db6ccea
--- /dev/null
+++ b/qwen_detect.py
@@ -0,0 +1,234 @@
+# 绂佺敤tokenizer骞惰锛堝繀椤绘斁鍦ㄦ墍鏈塱mport涔嬪墠锛�
+import torch
+import threading
+import time as time_sel
+from typing import Dict
+import qwen_task
+import requests
+import os
+
+import logging
+from transformers import AutoProcessor, AutoModelForVision2Seq
+from pymilvus import connections, Collection
+from logging.handlers import RotatingFileHandler
+import get_mem
+
+
+class ThreadPool:
+    def __init__(self):
+        #璇诲彇閰嶇疆鏂囦欢
+        self.config = {}
+        with open('./conf.txt', 'r', encoding='utf-8') as file:
+            for line in file:
+                # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+                line = line.strip()
+                # 璺宠繃绌鸿
+                if not line:
+                    continue
+                # 鍒嗗壊閿拰鍊�
+                if '=' in line:
+                    key, value = line.split('=', 1)
+                    # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+                    key = key.strip()
+                    value = value.strip()
+                    # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+                    self.config[key] = value
+        # 閰嶇疆鏃ュ織
+        # 纭繚鏃ュ織鐩綍瀛樺湪
+        log_dir = "logs"
+        os.makedirs(log_dir, exist_ok=True)
+        self.threads: Dict[str, threading.Thread] = {}
+        self.lock = threading.Lock()
+
+        self.device = "cuda" if torch.cuda.is_available() else "cpu"
+
+        # 鍒濆鍖杚wenvl妫�娴嬫ā鍨�
+        self.qwen_model = AutoModelForVision2Seq.from_pretrained(
+            "./Qwen2-VL-2B-Instruct", device_map="auto",
+            trust_remote_code=True,
+            torch_dtype=torch.float16
+        )
+
+        # default processer
+        self.qwen_tokenizer = AutoProcessor.from_pretrained("./Qwen2-VL-2B-Instruct")
+
+        # 鍒濆鍖朚ilvus闆嗗悎
+        connections.connect("default", host=self.config.get("milvusurl"), port=self.config.get("milvusport"))
+        # 鍔犺浇闆嗗悎
+        self.collection = Collection(name="smartobject")
+        self.collection.load()
+
+        #鏄惁鏇存柊
+        self._isupdate = False
+
+        # 鍒濆鍖栧叡浜唴瀛�
+        get_mem.smem_init()
+
+        # 閰嶇疆鏃ュ織
+        logging.basicConfig(
+            level=logging.INFO,
+            format='%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s',
+            datefmt='%Y-%m-%d %H:%M:%S',
+            handlers=[
+                # 鎸夊ぇ灏忚疆杞殑鏃ュ織鏂囦欢锛堟渶澶�10MB锛屼繚鐣�3涓浠斤級
+                RotatingFileHandler(
+                    filename=os.path.join(log_dir, 'start_log.log'),
+                    maxBytes=10 * 1024 * 1024,  # 10MB
+                    backupCount=3,
+                    encoding='utf-8'
+                ),
+                # 鍚屾椂杈撳嚭鍒版帶鍒跺彴
+                logging.StreamHandler()
+            ]
+        )
+
+    #鍚姩绾跨▼
+    def safe_start(self, target_func, camera_id):
+        """绾跨▼瀹夊叏鍚姩鏂规硶"""
+        def wrapped():
+            thread_name = threading.current_thread().name
+            try:
+                target_func(camera_id)
+            except Exception as e:
+                logging.error(f"绾跨▼寮傚父: {str(e)}", exc_info=True)
+
+        with self.lock:  # 纭繚绾跨▼瀹夊叏鍒涘缓
+            t = threading.Thread(
+                target=wrapped,
+                daemon=True  # 璁剧疆涓哄畧鎶ょ嚎绋�
+            )
+            t.start()
+            self.threads[camera_id] = t
+            return t
+
+    # 鍚姩绾跨▼浠诲姟
+    def worker(self, camera_id):
+        # 鍒濆鍖�
+        detect = qwen_task.detect_tasks()
+        detect._thread_name = f"{camera_id}"  # 璁剧疆鍚嶇О
+        detect.init_logging(f"{camera_id}")
+        # 鍒濆鍖栨娴嬫ā鍨�
+        detect.device = self.device
+        # 鍒濆鍖杚wen妯″瀷
+        detect.qwen_tokenizer = self.qwen_tokenizer
+        detect.qwen_model = self.qwen_model
+
+        # 鍒濆鍖朚ilvus闆嗗悎
+        detect.collection = self.collection
+
+        # 璁剧疆绾跨▼鍚姩鐘舵��
+        detect._running = True
+        while True:
+            try:
+                # 璇诲彇鍏变韩鍐呭瓨涓殑鍥剧墖
+                image_id = get_mem.smem_read_frame_qianwen(camera_id)
+                if image_id > 0:
+                    logging.info(f"璇诲彇鍥惧儚鎴愬姛: {image_id}")
+                    image_id = detect.tark_do(image_id,self.config.get("filesavepath"),self.config.get("ragurl"),self.config.get("max_tokens"))
+                    logging.info(f"澶勭悊鍥惧儚鎴愬姛: {image_id}")
+            except Exception as e:
+                logging.info(f"{detect._thread_name}绾跨▼閿欒:{e}")
+
+    #璋冪敤鏄惁闇�瑕佹洿鏂�
+    def isUpdate(self):
+        try:
+            # 瀹氫箟璇锋眰鐨� URL
+            url = self.config.get("isupdateurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.get(url)
+
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                data = response.json().get("data")
+                if data.get("isChange") == 1:
+                    return True
+                else:
+                    return False
+        except Exception as e:
+            logging.info(f"璋冪敤鏄惁闇�瑕佹洿鏂版椂鍑洪敊:URL:{self.config.get('isupdateurl')}:{e}")
+            return False
+
+    #淇敼鏄惁鏇存柊鐘舵��
+    def update_status(self):
+        try:
+            # 鏇存柊鐘舵��
+            url = self.config.get("updatestatusurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.post(url)
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                return True
+            else:
+                return False
+        except Exception as e:
+            logging.info(f"淇敼鏄惁鏇存柊鐘舵�佹椂鍑洪敊:URL:{self.config.get('updatestatusurl')}:{e}")
+            return False
+
+    def shutdown_all(self) -> None:
+        """娓呯悊鎵�鏈夌嚎绋�"""
+        with self.lock:
+            for camera_id, thread in list(self.threads.items()):
+                if thread.is_alive():
+                    thread.join(timeout=1)
+                del self.threads[camera_id]
+
+    #鑾峰彇浠诲姟
+    def getTaskconf(self,isupdate):
+        try:
+            # 瀹氫箟璇锋眰鐨� URL
+            url = self.config.get("gettaskconfurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.get(url)
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                data = response.json()
+                if isupdate:
+                    # 鏇存柊鐘舵��
+                    self.update_status()
+                return data.get("data")
+            else:
+                return []
+        except Exception as e:
+            logging.info(f"璋冪敤鑾峰彇浠诲姟鏃跺嚭閿�:URL:{self.config.get('gettaskconfurl')}:{e}")
+            return []
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+    pool = ThreadPool()
+    is_init = True
+    camera_data = pool.getTaskconf(False)
+    while True:
+        try:
+            pool._isupdate = False  # 鏄惁鏇存柊鏁版嵁
+            # 鏄惁闇�瑕佹洿鏂颁换鍔℃暟鎹�
+            if pool.isUpdate():
+                # 鑾峰彇鎽勫儚鏈轰换鍔�
+                camera_data = pool.getTaskconf(True)
+                pool._isupdate = True  # 鏇存柊鏁版嵁
+
+            if is_init:
+                if camera_data:
+                    for camera in camera_data:
+                        thread = pool.threads.get(camera.get("camera_id"))
+                        if not thread:
+                            logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+                            pool.safe_start(pool.worker, camera.get('camera_id'))
+                            logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+            if pool._isupdate:
+                logging.info(f"鏇存柊绾跨▼寮�濮�")
+                pool.shutdown_all()
+                if camera_data:
+                    for camera in camera_data:
+                        thread = pool.threads.get(camera.get("camera_id"))
+                        if not thread:
+                            logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+                            pool.safe_start(pool.worker, camera.get('camera_id'))
+                            logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+                logging.info(f"鏇存柊绾跨▼缁撴潫")
+
+            is_init = False
+            time_sel.sleep(1)
+        except Exception as e:
+            logging.info(f"涓荤嚎绋嬫湭鐭ラ敊璇�:{e}")
diff --git a/qwen_ollama.py b/qwen_ollama.py
new file mode 100644
index 0000000..92a197a
--- /dev/null
+++ b/qwen_ollama.py
@@ -0,0 +1,332 @@
+import asyncio
+import base64
+import io
+import json
+import os
+import re
+
+import requests
+import torch
+import logging
+from PIL import Image
+from logging.handlers import RotatingFileHandler
+
+
+class detect_tasks():
+    def __init__(self):
+        # 绾跨▼鍚嶇О
+        self._thread_name = ''
+
+        # 鍒濆鍖朚ilvus闆嗗悎
+        self.collection = None
+
+    def remove_duplicate_lines(self, text):
+
+        seen = set()
+        result = []
+        for line in text.split('銆�'):  # 鎸夊彞鍙峰垎鍓�
+            if line.strip() and line not in seen:
+                seen.add(line)
+                result.append(line)
+        return '銆�'.join(result)
+
+    def remove_duplicate_lines_d(self, text):
+        seen = set()
+        result = []
+        for line in text.split(','):  # 鎸夊彞鍙峰垎鍓�
+            if line.strip() and line not in seen:
+                seen.add(line)
+                result.append(line)
+        return '銆�'.join(result)
+
+    def remove_duplicate_lines_n(self, text):
+        seen = set()
+        result = []
+        for line in text.split('\n'):  # 鎸夊彞鍙峰垎鍓�
+            if line.strip() and line not in seen:
+                seen.add(line)
+                result.append(line)
+        return '銆�'.join(result)
+
+    def init_logging(self, logname):
+        # 鍒涘缓瀹炰緥涓撳睘logger
+        self.logger = logging.getLogger(f"{self.__class__}_{id(self)}")
+        self.logger.setLevel(logging.INFO)
+        # 閬垮厤閲嶅娣诲姞handler
+        if not self.logger.handlers:
+            handler = RotatingFileHandler(
+                filename=os.path.join("logs", logname + '_log.log'),
+                maxBytes=10 * 1024 * 1024,
+                backupCount=3,
+                encoding='utf-8'
+            )
+            formatter = logging.Formatter(
+                '%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s'
+            )
+            handler.setFormatter(formatter)
+            self.logger.addHandler(handler)
+
+    def image_desc(self, image_path, ollama_url, ollama_mode="qwen2.5vl:3b"):
+        try:
+            image_des = None
+            # 鍥剧墖棰勫鐞�
+            img = Image.open(image_path)
+            buffered = io.BytesIO()
+            img.save(buffered, format="JPEG", quality=85)
+            img_str = base64.b64encode(buffered.getvalue()).decode('utf-8')
+            # 璋冪敤API
+            response = requests.post(
+                f"{ollama_url}/api/generate",
+                json={
+                    "model": ollama_mode,
+                    "prompt": "璇锋寜浠ヤ笅瑕佹眰鎻忚堪鍥剧墖锛歕n1. 鍒楀嚭涓昏鐗╀綋\n2.涓嶈繘琛屾帹鐞嗗拰think\n杩斿洖灏忎簬2000瀛楃殑鏁存鎻忚堪,鎻忚堪涓殑鐗╀綋淇℃伅涓嶅姞鏁板瓧搴忓彿",
+                    "images": [img_str],
+                    "options": {
+                        "num_gpu_layers": 35
+                    },
+                    "stream": False  # 闈炴祦寮�
+                },
+                headers={"Content-Type": "application/json"}
+            )
+            result = response.json()
+            if result and result["response"]:
+                image_des = (result["response"]).replace('\n', '')
+                if len(image_des) > 4 and image_des.startswith("杩欏紶鍥剧墖"):
+                    image_des = image_des[4:]
+
+                image_des = self.remove_duplicate_lines(image_des)
+                image_des = self.remove_duplicate_lines_d(image_des)
+                image_des = self.remove_duplicate_lines_n(image_des)
+                # self.logger.info(image_des)
+            else:
+                self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屽浘鐗囨弿杩版椂鍑洪敊:{image_path, result, response}")
+            return image_des
+        except Exception as e:
+            self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屽浘鐗囨弿杩版椂鍑洪敊:{image_path, e}")
+            return None
+
+    def get_rule(self, ragurl):
+        try:
+            rule_text = None
+            search_data = {
+                "collection_name": "smart_rule",
+                "query_text": "",
+                "search_mode": "hybrid",
+                "limit": 100,
+                "weight_dense": 0.7,
+                "weight_sparse": 0.3,
+                "filter_expr": "",
+                "output_fields": ["text"]
+            }
+            response = requests.post(ragurl + "/search", json=search_data)
+            results = response.json().get('results')
+            rule_text = ""
+            ruleid = 1
+            for rule in results:
+                if rule['score'] >= 0:
+                    rule_text = rule_text + str(ruleid) + ". " + rule['entity'].get('text') + ";\n"
+                    ruleid = ruleid + 1
+            # self.logger.info(len(rule_text))
+            else:
+                self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛岃幏鍙栬鍒欐椂鍑洪敊:{response}")
+            return rule_text
+        except Exception as e:
+            self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛岃幏鍙栬鍒欐椂鍑洪敊:{e}")
+            return None
+
+    def image_rule_chat(self, image_des, rule_text, ollama_url, ollama_mode="qwen2.5vl:3b"):
+        try:
+            is_waning = 0
+
+            # 璇锋眰鍐呭
+            content = (
+                f"鍥剧墖鎻忚堪鍐呭涓猴細\n{image_des}\n瑙勫垯鍐呭锛歕n{rule_text}銆俓n璇烽獙璇佸浘鐗囨弿杩颁腑鏄惁鏈夌鍚堣鍒欑殑鍐呭锛屼笉杩涜鎺ㄧ悊鍜宼hink銆傝繑鍥炵粨鏋滄牸寮忎负[xxx绗﹀悎鐨勮鍒檌d]锛屽鏋滄病鏈夎繑鍥瀃]")
+
+            # API璋冪敤
+            response = requests.post(
+                # ollama鍦板潃
+                url=f"{ollama_url}/api/chat",
+                json={
+                    # 榛樿妯″瀷
+                    "model": ollama_mode,
+                    "messages": [
+                        {"role": "user", "content": content}
+                    ],
+                    "stream": False  # 鍏抽棴娴佸紡杈撳嚭
+                }
+            )
+            # 缁撴灉澶勭悊
+            ret = response.json()["message"]["content"]
+            if len(ret) > 2:
+                is_waning = 1
+            # self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛岃鍒欏尮閰嶆椂鍑洪敊:{image_des, rule_text,ret, response, ollama_url, ollama_mode}")
+            return is_waning
+        except Exception as e:
+            self.logger.info(
+                f"{self._thread_name}绾跨▼锛氭墽琛岃鍒欏尮閰嶆椂鍑洪敊:{image_des, rule_text, ollama_url, ollama_mode, e}")
+            return None
+
+    # 闅愭偅鎻忚堪
+    def image_rule_chat_with_detail(self,filedata, rule_text, ollama_url, ollama_mode="qwen2.5vl:3b"):
+
+        # API璋冪敤
+        response = requests.post(
+            # ollama鍦板潃
+            url=f"{ollama_url}/chat",
+            json={
+                "prompt":"",
+                # 璇锋眰鍐呭
+                "messages": [
+                    {
+                        "role": "user",
+                        "content": f"璇锋牴鎹绔犲埗搴{filedata}]\n鏌ユ壘[{rule_text}]鐨勫畨鍏ㄩ殣鎮f弿杩帮紝涓嶈繘琛屾帹鐞嗗拰think銆傝繑鍥炰俊鎭皬浜�800瀛�"
+                    }
+                ],
+                # 鎸囧畾妯″瀷
+                "llm_name": "qwen3:8b",
+                "stream": False,    # 鍏抽棴娴佸紡杈撳嚭
+                "gen_conf": {
+                    "temperature": 0.7,  # 鎺у埗鐢熸垚闅忔満鎬�
+                    "max_tokens": 800   # 鏈�澶ц緭鍑洪暱搴�
+                }
+            }
+        )
+        # 浠巎son鎻愬彇data瀛楁鍐呭
+        ret = response.json()["data"]
+        # 绉婚櫎<think>鏍囩鍜屽唴瀹�
+        ret = re.sub(r'<think>.*?</think>', '', ret, flags=re.DOTALL)
+        # 瀛楃涓叉竻鐞�,绉婚櫎绌烘牸,鍒惰〃绗�,鎹㈣绗�,鏄熷彿
+        ret = ret.replace(" ", "").replace("\t", "").replace("\n", "").replace("**","")
+        print(ret)
+        return ret
+    #澶勭悊寤鸿
+    def image_rule_chat_suggestion(self, rule_text, ollama_url, ollama_mode="qwen2.5vl:3b"):
+        self.logger.info("----------------------------------------------------------------")
+        content = (
+            f"璇锋牴鎹繚瑙勫唴瀹筟{rule_text}]\n杩涜杩斿洖澶勭悊杩濊寤鸿锛屼笉杩涜鎺ㄧ悊鍜宼hink銆傝繑鍥炵簿鍑嗕俊鎭�")
+        response = requests.post(
+            url=f"{ollama_url}/chat",
+            json={
+
+                "llm_name": "qwen3:8b",
+                "messages": [
+                    {"role": "user", "content": content}
+                ],
+                "stream": False  # 鍏抽棴娴佸紡杈撳嚭
+            }
+        )
+        ret = response.json()["data"]
+        ret = re.sub(r'<think>.*?</think>', '', ret, flags=re.DOTALL)
+        ret = ret.replace(" ", "").replace("\t", "").replace("\n", "").replace("**","")
+        print(ret)
+        return ret
+
+        # print(response.json())
+        # ret = response.json()["detail"]
+
+    def get_filedata(self, searchtext, ragurl):
+        search_data = {
+            "collection_name": "smart_knowledge",
+            "query_text": searchtext,
+            "search_mode": "hybrid",
+            "limit": 100,
+            "weight_dense": 0.7,
+            "weight_sparse": 0.3,
+            "filter_expr": "",
+            "output_fields": ["text"]
+        }
+        response = requests.post(ragurl + "/search", json=search_data)
+        results = response.json().get('results')
+        text = ""
+        for rule in results:
+            text = text + rule['entity'].get('text') + ";\n"
+
+        return text
+
+    async def insert_json_data(self, ragurl, data):
+        try:
+            data = {'collection_name': "smartrag", "data": data, "description": ""}
+            requests.post(ragurl + "/insert_json_data", json=data, timeout=(0.3, 0.3))
+            # self.logger.info(f"璋冪敤褰曞儚鏈嶅姟:{ragurl, data}")
+        except Exception as e:
+            # self.logger.info(f"{self._thread_name}绾跨▼锛氳皟鐢ㄥ綍鍍忔椂鍑洪敊:鍦板潃锛歿ragurl}锛歿e}")
+            return
+
+    def tark_do(self, image_id, ollamaurl, ragurl, ollamamode, ragmode):
+        try:
+            # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+            is_waning = 0
+            res_a = self.collection.query(
+                expr=f"id == 458942504686042840",
+                output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "video_point_name", "task_id",
+                               "task_name", "event_level_id", "event_level_name",
+                               "video_point_id", "detect_num", "is_waning", "waning_value", "rule_id", "detect_id",
+                               "detect_time", "image_path", "image_desc_path", "video_path","risk_description","suggestion","knowledge_id"],
+                consistency_level="Strong"
+            )
+
+            if not res_a:
+                self.logger.info(f"{self._thread_name}绾跨▼锛氭湭鎵惧埌ID涓� {image_id} 鐨勮褰�")
+                return 0
+
+
+            image_des = self.image_desc(f"/opt/smart/img/1748763385.245874.jpg", ollamaurl, ollamamode)
+            risk_description = ""
+            suggestion = ""
+            if image_des:
+                is_waning = self.image_rule_chat(image_des, res_a[0]['waning_value'], ollamaurl, ollamamode)
+
+                if is_waning == 0:
+
+                    filedata = self.get_filedata(res_a[0]['waning_value'], ragurl)
+                    risk_description = self.image_rule_chat_with_detail(filedata,res_a[0]['waning_value'], ragurl, ragmode)
+                    suggestion = self.image_rule_chat_suggestion(res_a[0]['waning_value'], ragurl, ragmode)
+
+            # 鏁版嵁缁�
+            data = {
+                "id": image_id,
+                "event_level_id": res_a[0]['event_level_id'],  # event_level_id
+                "event_level_name": res_a[0]['event_level_name'],  # event_level_id
+                "rule_id": res_a[0]["rule_id"],
+                "video_point_id": res_a[0]['video_point_id'],  # video_point_id
+                "video_point_name": res_a[0]['video_point_name'],
+                "is_waning": is_waning,
+                "zh_desc_class": image_des,  # text_vector
+                "bounding_box": res_a[0]['bounding_box'],  # bounding_box
+                "task_id": res_a[0]['task_id'],  # task_id
+                "task_name": res_a[0]['task_name'],  # task_id
+                "detect_id": res_a[0]['detect_id'],  # detect_id
+                "detect_time": res_a[0]['detect_time'],  # detect_time
+                "detect_num": res_a[0]['detect_num'],
+                "waning_value": res_a[0]['waning_value'],
+                "image_path": res_a[0]['image_path'],  # image_path
+                "image_desc_path": res_a[0]['image_desc_path'],  # image_desc_path
+                "video_path": res_a[0]['video_path'],
+                "text_vector": res_a[0]['text_vector'],
+                "risk_description": risk_description,
+                "suggestion": suggestion,
+                "knowledge_id": res_a[0]['knowledge_id']
+            }
+
+
+
+            # 淇濆瓨鍒癿ilvus
+            image_id = self.collection.upsert(data).primary_keys
+            data = {
+                "id": str(image_id[0]),
+                "video_point_id": res_a[0]['video_point_id'],
+                "video_path": res_a[0]["video_point_name"],
+                "zh_desc_class": image_des,
+                "detect_time": res_a[0]['detect_time'],
+                "image_path": f"{res_a[0]['image_path']}",
+                "task_name": res_a[0]["task_name"],
+                "event_level_name": res_a[0]["event_level_name"],
+                "rtsp_address": f"{res_a[0]['video_path']}"
+            }
+            # 璋冪敤rag
+            asyncio.run(self.insert_json_data(ragurl, data))
+            return image_id
+        except Exception as e:
+            self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屾ā鍨嬭В鏋愭椂鍑洪敊:浠诲姟锛歿image_id} :{e}")
+            return 0
+
diff --git a/qwen_ollama_detect.py b/qwen_ollama_detect.py
new file mode 100644
index 0000000..df78f7d
--- /dev/null
+++ b/qwen_ollama_detect.py
@@ -0,0 +1,219 @@
+# 绂佺敤tokenizer骞惰锛堝繀椤绘斁鍦ㄦ墍鏈塱mport涔嬪墠锛�
+import torch
+import threading
+import time as time_sel
+from typing import Dict
+
+import qwen_ollama
+import requests
+import os
+
+import logging
+from transformers import AutoProcessor, AutoModelForVision2Seq
+from pymilvus import connections, Collection
+from logging.handlers import RotatingFileHandler
+import get_mem
+
+
+class ThreadPool:
+    def __init__(self):
+        # 璇诲彇閰嶇疆鏂囦欢
+        self.config = {}
+        with open('./conf.txt', 'r', encoding='utf-8') as file:
+            for line in file:
+                # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+                line = line.strip()
+                # 璺宠繃绌鸿
+                if not line:
+                    continue
+                # 鍒嗗壊閿拰鍊�
+                if '=' in line:
+                    key, value = line.split('=', 1)
+                    # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+                    key = key.strip()
+                    value = value.strip()
+                    # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+                    self.config[key] = value
+        # 閰嶇疆鏃ュ織
+        # 纭繚鏃ュ織鐩綍瀛樺湪
+        log_dir = "logs"
+        os.makedirs(log_dir, exist_ok=True)
+        self.threads: Dict[str, threading.Thread] = {}
+        self.lock = threading.Lock()
+
+        # 鍒濆鍖朚ilvus闆嗗悎
+        connections.connect("default", host=self.config.get("milvusurl"), port=self.config.get("milvusport"))
+        # 鍔犺浇闆嗗悎
+        self.collection = Collection(name="smartobject")
+        self.collection.load()
+
+        # 鏄惁鏇存柊
+        self._isupdate = False
+
+        # 鍒濆鍖栧叡浜唴瀛�
+        get_mem.smem_init()
+
+        # 閰嶇疆鏃ュ織
+        logging.basicConfig(
+            level=logging.INFO,
+            format='%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s',
+            datefmt='%Y-%m-%d %H:%M:%S',
+            handlers=[
+                # 鎸夊ぇ灏忚疆杞殑鏃ュ織鏂囦欢锛堟渶澶�10MB锛屼繚鐣�3涓浠斤級
+                RotatingFileHandler(
+                    filename=os.path.join(log_dir, 'start_log.log'),
+                    maxBytes=10 * 1024 * 1024,  # 10MB
+                    backupCount=3,
+                    encoding='utf-8'
+                ),
+                # 鍚屾椂杈撳嚭鍒版帶鍒跺彴
+                logging.StreamHandler()
+            ]
+        )
+
+    # 鍚姩绾跨▼
+    def safe_start(self, target_func, camera_id):
+        """绾跨▼瀹夊叏鍚姩鏂规硶"""
+
+        def wrapped():
+            thread_name = threading.current_thread().name
+            try:
+                target_func(camera_id)
+            except Exception as e:
+                logging.error(f"绾跨▼寮傚父: {str(e)}", exc_info=True)
+
+        with self.lock:  # 纭繚绾跨▼瀹夊叏鍒涘缓
+            t = threading.Thread(
+                target=wrapped,
+                daemon=True  # 璁剧疆涓哄畧鎶ょ嚎绋�
+            )
+            t.start()
+            self.threads[camera_id] = t
+            return t
+
+    # 鍚姩绾跨▼浠诲姟
+    def worker(self, camera_id):
+        # 鍒濆鍖�
+        detect = qwen_ollama.detect_tasks()
+        detect._thread_name = f"{camera_id}"  # 璁剧疆鍚嶇О
+        detect.init_logging(f"{camera_id}")
+        # 鍒濆鍖朚ilvus闆嗗悎
+        detect.collection = self.collection
+
+        while True:
+            try:
+                # 璇诲彇鍏变韩鍐呭瓨涓殑鍥剧墖
+                # image_id = get_mem.smem_read_frame_qianwen(camera_id)
+                # if image_id > 0:
+                #    logging.info(f"璇诲彇鍥惧儚鎴愬姛: {image_id}")
+
+                image_id = detect.tark_do(458942504686042840, self.config.get("ollamaurl"), self.config.get("ragurl"),
+                                          self.config.get("ollamamode"), self.config.get("ragmode"))
+                logging.info(f"澶勭悊鍥惧儚鎴愬姛: {image_id}")
+            except Exception as e:
+                logging.info(f"{detect._thread_name}绾跨▼閿欒:{e}")
+
+    # 璋冪敤鏄惁闇�瑕佹洿鏂�
+    def isUpdate(self):
+        try:
+            # 瀹氫箟璇锋眰鐨� URL
+            url = self.config.get("isupdateurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.get(url)
+
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                data = response.json().get("data")
+                if data.get("isChange") == 1:
+                    return True
+                else:
+                    return False
+        except Exception as e:
+            logging.info(f"璋冪敤鏄惁闇�瑕佹洿鏂版椂鍑洪敊:URL:{self.config.get('isupdateurl')}:{e}")
+            return False
+
+    # 淇敼鏄惁鏇存柊鐘舵��
+    def update_status(self):
+        try:
+            # 鏇存柊鐘舵��
+            url = self.config.get("updatestatusurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.post(url)
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                return True
+            else:
+                return False
+        except Exception as e:
+            logging.info(f"淇敼鏄惁鏇存柊鐘舵�佹椂鍑洪敊:URL:{self.config.get('updatestatusurl')}:{e}")
+            return False
+
+    def shutdown_all(self) -> None:
+        """娓呯悊鎵�鏈夌嚎绋�"""
+        with self.lock:
+            for camera_id, thread in list(self.threads.items()):
+                if thread.is_alive():
+                    thread.join(timeout=1)
+                del self.threads[camera_id]
+
+    # 鑾峰彇浠诲姟
+    def getTaskconf(self, isupdate):
+        try:
+            # 瀹氫箟璇锋眰鐨� URL
+            url = self.config.get("gettaskconfurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.get(url)
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                data = response.json()
+                if isupdate:
+                    # 鏇存柊鐘舵��
+                    self.update_status()
+                return data.get("data")
+            else:
+                return []
+        except Exception as e:
+            logging.info(f"璋冪敤鑾峰彇浠诲姟鏃跺嚭閿�:URL:{self.config.get('gettaskconfurl')}:{e}")
+            return []
+
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+    pool = ThreadPool()
+    is_init = True
+    camera_data = pool.getTaskconf(False)
+    while True:
+        try:
+            pool._isupdate = False  # 鏄惁鏇存柊鏁版嵁
+            # 鏄惁闇�瑕佹洿鏂颁换鍔℃暟鎹�
+            if pool.isUpdate():
+                # 鑾峰彇鎽勫儚鏈轰换鍔�
+                camera_data = pool.getTaskconf(True)
+                pool._isupdate = True  # 鏇存柊鏁版嵁
+
+            if is_init:
+                if camera_data:
+                    for camera in camera_data:
+                        thread = pool.threads.get(camera.get("camera_id"))
+                        if not thread:
+                            logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+                            pool.safe_start(pool.worker, camera.get('camera_id'))
+                            logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+            if pool._isupdate:
+                logging.info(f"鏇存柊绾跨▼寮�濮�")
+                pool.shutdown_all()
+                if camera_data:
+                    for camera in camera_data:
+                        thread = pool.threads.get(camera.get("camera_id"))
+                        if not thread:
+                            logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+                            pool.safe_start(pool.worker, camera.get('camera_id'))
+                            logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+                logging.info(f"鏇存柊绾跨▼缁撴潫")
+
+            is_init = False
+            time_sel.sleep(1)
+        except Exception as e:
+            logging.info(f"涓荤嚎绋嬫湭鐭ラ敊璇�:{e}")
diff --git a/qwen_task.py b/qwen_task.py
new file mode 100644
index 0000000..1180264
--- /dev/null
+++ b/qwen_task.py
@@ -0,0 +1,150 @@
+import json
+import os
+import re
+
+import requests
+import torch
+import logging
+from PIL import Image
+from logging.handlers import RotatingFileHandler
+
+class detect_tasks():
+    def __init__(self):
+        #绾跨▼鍚嶇О
+        self._thread_name = ''
+        self.device = None
+        # 鍒濆鍖栨娴嬫ā鍨�
+        self.qwen_tokenizer = None
+        self.qwen_model = None
+
+        # 鍒濆鍖朚ilvus闆嗗悎
+        self.collection = None
+
+    def remove_duplicate_lines(self,text):
+        seen = set()
+        result = []
+        for line in text.split('銆�'):  # 鎸夊彞鍙峰垎鍓�
+            if line.strip() and line not in seen:
+                seen.add(line)
+                result.append(line)
+        return '銆�'.join(result)
+
+    def init_logging(self,logname):
+        # 鍒涘缓瀹炰緥涓撳睘logger
+        self.logger = logging.getLogger(f"{self.__class__}_{id(self)}")
+        self.logger.setLevel(logging.INFO)
+        # 閬垮厤閲嶅娣诲姞handler
+        if not self.logger.handlers:
+            handler = RotatingFileHandler(
+                filename=os.path.join("logs", logname+'_log.log'),
+                maxBytes=10 * 1024 * 1024,
+                backupCount=3,
+                encoding='utf-8'
+            )
+            formatter = logging.Formatter(
+                '%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s'
+            )
+            handler.setFormatter(formatter)
+            self.logger.addHandler(handler)
+
+    def tark_do(self,image_id,filesavepath,ragurl,max_tokens):
+        try :
+            # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+            res_a = self.collection.query(
+                expr=f"id == {image_id}",
+                output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "video_point_name", "task_id",
+                               "task_name","event_level_id","event_level_name",
+                               "video_point_id", "detect_num", "is_waning", "waning_value", "rule_id", "detect_id",
+                               "detect_time", "image_path", "image_desc_path","video_path"],
+                consistency_level="Strong"
+            )
+            # 鍥剧墖鍜岃棰戝湴鍧�
+            image = Image.open(f"{res_a[0]['image_desc_path']}").convert("RGB")  # 鏇挎崲涓烘偍鐨勫浘鐗囪矾寰�
+            conversation = [
+                {
+                    "role": "user",
+                    "content": [
+                        {
+                            "type": "image",
+                        },
+                        {"type": "text", "text": "璇锋寜浠ヤ笅瑕佹眰鎻忚堪鍥剧墖锛歕n1. 鍒楀嚭涓昏鐗╀綋\n2.涓嶈繘琛屾帹鐞嗗拰think\n杩斿洖灏忎簬2000瀛楃殑鏁存鎻忚堪,鎻忚堪涓殑鐗╀綋淇℃伅涓嶅姞鏁板瓧搴忓彿"},
+                    ],
+                }
+            ]
+
+            # Preprocess the inputs
+            self.logger.info("aaaa")
+            text_prompt = self.qwen_tokenizer.apply_chat_template(conversation, add_generation_prompt=True)
+            # Excepted output: '<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n<|vision_start|><|image_pad|><|vision_end|>Describe this image.<|im_end|>\n<|im_start|>assistant\n'
+            self.logger.info("bbbb")
+            inputs = self.qwen_tokenizer(
+                text=[text_prompt], images=[image], padding=True, return_tensors="pt"
+            )
+            inputs = inputs.to("cuda")
+            self.logger.info("cccc")
+            torch.cuda.empty_cache()
+            with torch.no_grad():
+                output_ids = self.qwen_model.generate(**inputs, max_new_tokens=50)
+            print(output_ids.device)
+            self.logger.info("dddd")
+            generated_ids = [
+                output_ids[len(input_ids):]
+                for input_ids, output_ids in zip(inputs.input_ids, output_ids)
+            ]
+            image_text = self.qwen_tokenizer.batch_decode(
+                generated_ids, skip_special_tokens=True, clean_up_tokenization_spaces=True
+            )
+            self.logger.info("ffff")
+            image_des = (image_text[0]).replace('\n', '')
+
+            if len(image_des)>4 and image_des.startswith("杩欏紶鍥剧墖"):
+                image_des = image_des[4:]
+            self.logger.info(image_des)
+            image_des = self.remove_duplicate_lines(image_des)
+
+            is_waning = 0
+
+            data = {
+                "id": image_id,
+                "event_level_id": res_a[0]['event_level_id'],  # event_level_id
+                "event_level_name": res_a[0]['event_level_name'],  # event_level_id
+                "rule_id": res_a[0]["rule_id"],
+                "video_point_id": res_a[0]['video_point_id'],  # video_point_id
+                "video_point_name": res_a[0]['video_point_name'],
+                "is_waning": is_waning,
+                "zh_desc_class": image_des,  # text_vector
+                "bounding_box": res_a[0]['bounding_box'],  # bounding_box
+                "task_id": res_a[0]['task_id'],  # task_id
+                "task_name": res_a[0]['task_name'],  # task_id
+                "detect_id": res_a[0]['detect_id'],  # detect_id
+                "detect_time": res_a[0]['detect_time'],  # detect_time
+                "detect_num": res_a[0]['detect_num'],
+                "waning_value": res_a[0]['waning_value'],
+                "image_path": res_a[0]['image_path'],  # image_path
+                "image_desc_path": res_a[0]['image_desc_path'],  # image_path
+                "video_path": res_a[0]['video_path'],
+                "text_vector": res_a[0]['text_vector']
+            }
+            # 淇濆瓨鍒癿ilvus
+            image_id = self.collection.upsert(data).primary_keys
+            data = {
+                "id": str(image_id[0]),
+                "video_point_id": res_a[0]['video_point_id'],
+                "video_path": res_a[0]["video_point_name"],
+                "zh_desc_class": image_des,
+                "detect_time": res_a[0]['detect_time'],
+                "image_path": f"{res_a[0]['image_path']}",
+                "task_name": res_a[0]["task_name"],
+                "event_level_name": res_a[0]["event_level_name"],
+                "rtsp_address": f"{res_a[0]['video_path']}"
+            }
+
+            data = {'collection_name': "smartrag","data": data,"description":""}
+            requests.post(ragurl+"/insert_json_data",
+                json=data
+            )
+            return image_id
+        except Exception as e:
+            self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屾ā鍨嬭В鏋愭椂鍑洪敊:浠诲姟锛歿image_id} :{e}")
+            return 0
+
diff --git a/qwen_test.py b/qwen_test.py
new file mode 100644
index 0000000..13b2187
--- /dev/null
+++ b/qwen_test.py
@@ -0,0 +1,36 @@
+from pymilvus import connections, Collection
+
+import qwen_ollama
+
+config = {}
+with open('./conf.txt', 'r', encoding='utf-8') as file:
+    for line in file:
+        # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+        line = line.strip()
+        # 璺宠繃绌鸿
+        if not line:
+            continue
+        # 鍒嗗壊閿拰鍊�
+        if '=' in line:
+            key, value = line.split('=', 1)
+            # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+            key = key.strip()
+            value = value.strip()
+            # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+            config[key] = value
+
+# 鍒濆鍖朚ilvus闆嗗悎
+connections.connect("default", host=config.get("milvusurl"), port=config.get("milvusport"))
+# 鍔犺浇闆嗗悎
+collection = Collection(name="smartobject")
+collection.load()
+
+detect = qwen_ollama.detect_tasks()
+detect._thread_name = f"1"  # 璁剧疆鍚嶇О
+detect.init_logging(f"1")
+# 鍒濆鍖朚ilvus闆嗗悎
+detect.collection = collection
+camera_data = [458671636370953916,458671636370953918,458671636370953922,458671636370953977]
+for image_id in camera_data:
+    print(detect.tark_do(image_id, config.get("ollamaurl"), config.get("ragurl"),config.get("ollamamode")))
+
diff --git a/qwen_vllm.py b/qwen_vllm.py
new file mode 100644
index 0000000..26c96bf
--- /dev/null
+++ b/qwen_vllm.py
@@ -0,0 +1,246 @@
+import asyncio
+import base64
+import io
+import json
+import os
+import re
+
+import requests
+import torch
+import logging
+from PIL import Image
+from logging.handlers import RotatingFileHandler
+
+class detect_tasks():
+    def __init__(self):
+        #绾跨▼鍚嶇О
+        self._thread_name = ''
+
+        # 鍒濆鍖朚ilvus闆嗗悎
+        self.collection = None
+        # 鍒濆鍖杔lm
+        self.llm = None
+
+    def remove_duplicate_lines(self,text):
+        seen = set()
+        result = []
+        for line in text.split('銆�'):  # 鎸夊彞鍙峰垎鍓�
+            if line.strip() and line not in seen:
+                seen.add(line)
+                result.append(line)
+        return '銆�'.join(result)
+    def remove_duplicate_lines_d(self,text):
+        seen = set()
+        result = []
+        for line in text.split(','):  # 鎸夊彞鍙峰垎鍓�
+            if line.strip() and line not in seen:
+                seen.add(line)
+                result.append(line)
+        return '銆�'.join(result)
+    def remove_duplicate_lines_n(self,text):
+        seen = set()
+        result = []
+        for line in text.split('\n'):  # 鎸夊彞鍙峰垎鍓�
+            if line.strip() and line not in seen:
+                seen.add(line)
+                result.append(line)
+        return '銆�'.join(result)
+
+    def init_logging(self,logname):
+        # 鍒涘缓瀹炰緥涓撳睘logger
+        self.logger = logging.getLogger(f"{self.__class__}_{id(self)}")
+        self.logger.setLevel(logging.INFO)
+        # 閬垮厤閲嶅娣诲姞handler
+        if not self.logger.handlers:
+            handler = RotatingFileHandler(
+                filename=os.path.join("logs", logname+'_log.log'),
+                maxBytes=10 * 1024 * 1024,
+                backupCount=3,
+                encoding='utf-8'
+            )
+            formatter = logging.Formatter(
+                '%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s'
+            )
+            handler.setFormatter(formatter)
+            self.logger.addHandler(handler)
+
+    def image_desc(self,image_path):
+        try:
+            image_des = None
+            # 鏋勯�犲妯℃�佹秷鎭�
+            messages = [
+                {
+                    "role": "user",
+                    "content": [
+                        {"type": "text", "text": "璇疯缁嗘弿杩板浘鐗囦腑鐨勭洰鏍囦俊鎭強鐗瑰緛銆傝繑鍥炴牸寮忎负鏁存鏂囧瓧鎻忚堪"},
+                        {
+                            "type": "image_url",
+                            "image_url": {
+                                "url": f"data:image/jpeg;base64,{self.image_to_base64(image_path)}"
+                            }
+                        }
+                    ]
+                }
+            ]
+
+            # 鍙戦�佽姹�
+            #self.logger.info("鍙戦�佽姹�")
+            response = self.llm.invoke(messages)
+            if response and response.content:
+                image_des = response.content
+                if len(image_des) > 4 and image_des.startswith("杩欏紶鍥剧墖"):
+                    image_des = image_des[4:]
+
+                image_des = self.remove_duplicate_lines(image_des)
+                image_des = self.remove_duplicate_lines_d(image_des)
+                image_des = self.remove_duplicate_lines_n(image_des)
+                #self.logger.info(image_des)
+            else:
+                self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屽浘鐗囨弿杩版椂鍑洪敊:{image_path, response}")
+            return image_des
+        except Exception as e:
+            self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屽浘鐗囨弿杩版椂鍑洪敊:{image_path,e}")
+            return None
+
+    def get_rule(self,ragurl):
+        try:
+            rule_text = None
+            search_data = {
+                "collection_name": "smart_rule",
+                "query_text": "",
+                "search_mode": "hybrid",
+                "limit": 100,
+                "weight_dense": 0.7,
+                "weight_sparse": 0.3,
+                "filter_expr": "",
+                "output_fields": ["text"]
+            }
+            response = requests.post(ragurl + "/search", json=search_data)
+            results = response.json().get('results')
+            rule_text = ""
+            ruleid = 1
+            for rule in results:
+                if rule['score'] >= 0:
+                    rule_text = rule_text + str(ruleid) + ". " + rule['entity'].get('text') + ";\n"
+                    ruleid = ruleid + 1
+            # self.logger.info(len(rule_text))
+            else:
+                self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛岃幏鍙栬鍒欐椂鍑洪敊:{response}")
+            return rule_text
+        except Exception as e:
+            self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛岃幏鍙栬鍒欐椂鍑洪敊:{e}")
+            return None
+
+    def image_rule_chat(self, image_des,rule_text, ragurl, rag_mode,max_tokens):
+        try:
+            content = (
+                f"鍥剧墖鎻忚堪鍐呭涓猴細\n{image_des}\n瑙勫垯鍐呭锛歕n{rule_text}銆俓n璇烽獙璇佸浘鐗囨弿杩颁腑鏄惁鏈夌鍚堣鍒欑殑鍐呭锛屼笉杩涜鎺ㄧ悊鍜宼hink銆傝繑鍥炵粨鏋滄牸寮忎负[xxx绗﹀悎鐨勮鍒檌d]锛屽鏋滄病鏈夎繑鍥瀃]")
+            # self.logger.info(content)
+            #self.logger.info(len(content))
+            search_data = {
+                "prompt": "",
+                "messages": [
+                    {
+                        "role": "user",
+                        "content": content
+                    }
+                ],
+                "llm_name": rag_mode,
+                "stream": False,
+                "gen_conf": {
+                    "temperature": 0.7,
+                    "max_tokens": max_tokens
+                }
+            }
+            response = requests.post(ragurl + "/chat", json=search_data)
+            results = response.json().get('data')
+            #self.logger.info(len(results))
+            # self.logger.info(results)
+            ret = re.sub(r'<think>.*?</think>', '', results, flags=re.DOTALL)
+            ret = ret.replace(" ", "").replace("\t", "").replace("\n", "")
+            is_waning = 0
+            if len(ret) > 2:
+                is_waning = 1
+            return is_waning
+        except Exception as e:
+            self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛岃鍒欏尮閰嶆椂鍑洪敊:{image_des, rule_text, ragurl, rag_mode,e}")
+            return None
+
+    async def insert_json_data(self, ragurl, data):
+        try:
+            data = {'collection_name': "smartrag", "data": data, "description": ""}
+            requests.post(ragurl + "/insert_json_data", json=data, timeout=(0.3, 0.3))
+            #self.logger.info(f"璋冪敤褰曞儚鏈嶅姟:{ragurl, data}")
+        except Exception as e:
+            #self.logger.info(f"{self._thread_name}绾跨▼锛氳皟鐢ㄥ綍鍍忔椂鍑洪敊:鍦板潃锛歿ragurl}锛歿e}")
+            return
+
+    # 澶勭悊澶氭ā鎬佽緭鍏ワ紙绀轰緥锛氭枃鏈�+鍥惧儚锛�
+    def image_to_base64(self,image_path):
+        with open(image_path, "rb") as img_file:
+            return base64.b64encode(img_file.read()).decode('utf-8')
+
+    def tark_do(self,res,ragurl,rag_mode,max_tokens):
+        try :
+            # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+            is_waning = 0
+            is_desc = 0
+            #res_a = self.collection.query(
+            #    expr=f"id == {image_id}",
+            #    output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "video_point_name", "task_id",
+            #                   "task_name","event_level_id","event_level_name",
+            #                   "video_point_id", "detect_num", "is_waning", "waning_value", "rule_id", "detect_id",
+            #                   "detect_time", "image_path", "image_desc_path", "video_path"],
+            #    consistency_level="Strong"
+            #)
+            image_des = self.image_desc(f"{res['image_desc_path']}")
+            if image_des:
+                #rule_text = self.get_rule(ragurl)
+                is_waning = self.image_rule_chat(image_des,res['waning_value'],ragurl,rag_mode,max_tokens)
+                is_desc = 2
+            else:
+                is_waning = 0
+                is_desc = 3
+            data = {
+                "id": res['id'],
+                "event_level_id": res['event_level_id'],  # event_level_id
+                "event_level_name": res['event_level_name'],  # event_level_id
+                "rule_id": res["rule_id"],
+                "video_point_id": res['video_point_id'],  # video_point_id
+                "video_point_name": res['video_point_name'],
+                "is_waning": is_waning,
+                "is_desc": is_desc,
+                "zh_desc_class": image_des,  # text_vector
+                "bounding_box": res['bounding_box'],  # bounding_box
+                "task_id": res['task_id'],  # task_id
+                "task_name": res['task_name'],  # task_id
+                "detect_id": res['detect_id'],  # detect_id
+                "detect_time": res['detect_time'],  # detect_time
+                "detect_num": res['detect_num'],
+                "waning_value": res['waning_value'],
+                "image_path": res['image_path'],  # image_path
+                "image_desc_path": res['image_desc_path'],  # image_desc_path
+                "video_path": res['video_path'],
+                "text_vector": res['text_vector']
+            }
+            # 淇濆瓨鍒癿ilvus
+            image_id = self.collection.upsert(data).primary_keys
+            if is_desc == 2 :
+                data = {
+                    "id": str(image_id[0]),
+                    "video_point_id": res['video_point_id'],
+                    "video_path": res["video_point_name"],
+                    "zh_desc_class": image_des,
+                    "detect_time": res['detect_time'],
+                    "image_path": f"{res['image_path']}",
+                    "task_name": res["task_name"],
+                    "event_level_name": res["event_level_name"],
+                    "rtsp_address": f"{res['video_path']}"
+                }
+                #璋冪敤rag
+                asyncio.run(self.insert_json_data(ragurl, data))
+            return image_id
+        except Exception as e:
+            self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屾ā鍨嬭В鏋愭椂鍑洪敊:浠诲姟锛歿 res['id']} :{e}")
+            return 0
+
diff --git a/qwen_vllm_detect.py b/qwen_vllm_detect.py
new file mode 100644
index 0000000..f3af0d1
--- /dev/null
+++ b/qwen_vllm_detect.py
@@ -0,0 +1,256 @@
+# 绂佺敤tokenizer骞惰锛堝繀椤绘斁鍦ㄦ墍鏈塱mport涔嬪墠锛�
+from operator import itemgetter
+
+import torch
+import threading
+import time as time_sel
+from typing import Dict
+
+import qwen_vllm
+import requests
+import os
+
+import logging
+from transformers import AutoProcessor, AutoModelForVision2Seq
+from pymilvus import connections, Collection
+from logging.handlers import RotatingFileHandler
+import get_mem
+from langchain_openai import ChatOpenAI
+
+from qwen_vllm_thread import qwen_vllm_thread
+
+
+class ThreadPool:
+    def __init__(self):
+        #璇诲彇閰嶇疆鏂囦欢
+        self.config = {}
+        with open('./conf.txt', 'r', encoding='utf-8') as file:
+            for line in file:
+                # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+                line = line.strip()
+                # 璺宠繃绌鸿
+                if not line:
+                    continue
+                # 鍒嗗壊閿拰鍊�
+                if '=' in line:
+                    key, value = line.split('=', 1)
+                    # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+                    key = key.strip()
+                    value = value.strip()
+                    # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+                    self.config[key] = value
+        # 閰嶇疆鏃ュ織
+        # 纭繚鏃ュ織鐩綍瀛樺湪
+        log_dir = "logs"
+        os.makedirs(log_dir, exist_ok=True)
+        self.threads: Dict[str, threading.Thread] = {}
+        self.lock = threading.Lock()
+        # 鍒濆鍖朚ilvus闆嗗悎
+        connections.connect("default", host=self.config.get("milvusurl"), port=self.config.get("milvusport"))
+        # 鍔犺浇闆嗗悎
+        self.collection = Collection(name="smartobject")
+        self.collection.load()
+        #鏄惁鏇存柊
+        self._isupdate = False
+
+        # 鍒濆鍖栧叡浜唴瀛�
+        get_mem.smem_init()
+
+        # 閰嶇疆鏃ュ織
+        logging.basicConfig(
+            level=logging.INFO,
+            format='%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s',
+            datefmt='%Y-%m-%d %H:%M:%S',
+            handlers=[
+                # 鎸夊ぇ灏忚疆杞殑鏃ュ織鏂囦欢锛堟渶澶�10MB锛屼繚鐣�3涓浠斤級
+                RotatingFileHandler(
+                    filename=os.path.join(log_dir, 'start_log.log'),
+                    maxBytes=10 * 1024 * 1024,  # 10MB
+                    backupCount=3,
+                    encoding='utf-8'
+                ),
+                # 鍚屾椂杈撳嚭鍒版帶鍒跺彴
+                logging.StreamHandler()
+            ]
+        )
+
+    #鍚姩绾跨▼
+    def safe_start(self, target_func, camera_id):
+        """绾跨▼瀹夊叏鍚姩鏂规硶"""
+        def wrapped():
+            thread_name = threading.current_thread().name
+            try:
+                target_func(camera_id)
+            except Exception as e:
+                logging.error(f"绾跨▼寮傚父: {str(e)}", exc_info=True)
+
+        with self.lock:  # 纭繚绾跨▼瀹夊叏鍒涘缓
+            t = threading.Thread(
+                target=wrapped,
+                daemon=True  # 璁剧疆涓哄畧鎶ょ嚎绋�
+            )
+            t.start()
+            self.threads[camera_id] = t
+            return t
+
+    # 鍚姩绾跨▼浠诲姟
+    def worker(self, camera_id):
+        pool = qwen_vllm_thread(int(self.config.get("threadnum")),camera_id,self.config)
+        while True:
+            try:
+                res_a = self.collection.query(
+                    expr=f"is_desc == 0 and video_point_id=={camera_id}",
+                    output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "video_point_name", "task_id",
+                                   "task_name", "event_level_id", "event_level_name",
+                                   "video_point_id", "detect_num", "is_waning", "is_desc","waning_value", "rule_id", "detect_id",
+                                   "detect_time", "image_path", "image_desc_path", "video_path"],
+                    consistency_level="Strong",
+                    order_by_field="id",  # 鎸塱d瀛楁鎺掑簭
+                    order_by_type="desc"  # 闄嶅簭鎺掑垪
+                )
+
+                # 璇诲彇鍏变韩鍐呭瓨涓殑鍥剧墖
+                # image_id = get_mem.smem_read_frame_qianwen(camera_id)
+                if len(res_a) > 0:
+                    sorted_results = sorted(res_a, key=itemgetter("id"), reverse=True)
+                    # 鏌ヨ鍓峃涓渶澶х殑ID
+                    num = int(self.config.get("threadnum"))-1
+                    res_a = sorted_results[:num]
+                    for res in res_a:
+                        data = {
+                            "id": res['id'],
+                            "event_level_id": res['event_level_id'],  # event_level_id
+                            "event_level_name": res['event_level_name'],  # event_level_id
+                            "rule_id": res["rule_id"],
+                            "video_point_id": res['video_point_id'],  # video_point_id
+                            "video_point_name": res['video_point_name'],
+                            "is_waning": 0,
+                            "is_desc": 1,
+                            "zh_desc_class": res['zh_desc_class'],  # text_vector
+                            "bounding_box": res['bounding_box'],  # bounding_box
+                            "task_id": res['task_id'],  # task_id
+                            "task_name": res['task_name'],  # task_id
+                            "detect_id": res['detect_id'],  # detect_id
+                            "detect_time": res['detect_time'],  # detect_time
+                            "detect_num": res['detect_num'],
+                            "waning_value": res['waning_value'],
+                            "image_path": res['image_path'],  # image_path
+                            "image_desc_path": res['image_desc_path'],  # image_desc_path
+                            "video_path": res['video_path'],
+                            "text_vector": res['text_vector']
+                        }
+                        #logging.info(f"璇诲彇鍥惧儚鎴愬姛: {res['id']}")
+                        # 淇濆瓨鍒癿ilvus
+                        image_id = self.collection.upsert(data).primary_keys
+                        res['id']  = image_id[0]
+                        #logging.info(f"璇诲彇鍥惧儚鎴愬姛: {image_id}")
+                        image_id = pool.submit(res)
+                        #image_id = pool.tark_do(image_id,self.config.get("ragurl"),self.config.get("ragmode"),self.config.get("max_tokens"))
+                        #logging.info(f"澶勭悊鍥惧儚鎴愬姛: {image_id}")
+                    sorted_results = None
+            except Exception as e:
+                logging.info(f"{camera_id}绾跨▼閿欒:{e}")
+
+    #璋冪敤鏄惁闇�瑕佹洿鏂�
+    def isUpdate(self):
+        try:
+            # 瀹氫箟璇锋眰鐨� URL
+            url = self.config.get("isupdateurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.get(url)
+
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                data = response.json().get("data")
+                if data.get("isChange") == 1:
+                    return True
+                else:
+                    return False
+        except Exception as e:
+            logging.info(f"璋冪敤鏄惁闇�瑕佹洿鏂版椂鍑洪敊:URL:{self.config.get('isupdateurl')}:{e}")
+            return False
+
+    #淇敼鏄惁鏇存柊鐘舵��
+    def update_status(self):
+        try:
+            # 鏇存柊鐘舵��
+            url = self.config.get("updatestatusurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.post(url)
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                return True
+            else:
+                return False
+        except Exception as e:
+            logging.info(f"淇敼鏄惁鏇存柊鐘舵�佹椂鍑洪敊:URL:{self.config.get('updatestatusurl')}:{e}")
+            return False
+
+    def shutdown_all(self) -> None:
+        """娓呯悊鎵�鏈夌嚎绋�"""
+        with self.lock:
+            for camera_id, thread in list(self.threads.items()):
+                if thread.is_alive():
+                    thread.join(timeout=1)
+                del self.threads[camera_id]
+
+    #鑾峰彇浠诲姟
+    def getTaskconf(self,isupdate):
+        try:
+            # 瀹氫箟璇锋眰鐨� URL
+            url = self.config.get("gettaskconfurl")
+            # 鍙戦�� GET 璇锋眰
+            response = requests.get(url)
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                data = response.json()
+                if isupdate:
+                    # 鏇存柊鐘舵��
+                    self.update_status()
+                return data.get("data")
+            else:
+                return []
+        except Exception as e:
+            logging.info(f"璋冪敤鑾峰彇浠诲姟鏃跺嚭閿�:URL:{self.config.get('gettaskconfurl')}:{e}")
+            return []
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+    pool = ThreadPool()
+    is_init = True
+    camera_data = pool.getTaskconf(False)
+    while True:
+        try:
+            pool._isupdate = False  # 鏄惁鏇存柊鏁版嵁
+            # 鏄惁闇�瑕佹洿鏂颁换鍔℃暟鎹�
+            if pool.isUpdate():
+                # 鑾峰彇鎽勫儚鏈轰换鍔�
+                camera_data = pool.getTaskconf(True)
+                pool._isupdate = True  # 鏇存柊鏁版嵁
+
+            if is_init:
+                if camera_data:
+                    for camera in camera_data:
+                        thread = pool.threads.get(camera.get("camera_id"))
+                        if not thread:
+                            logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+                            pool.safe_start(pool.worker, camera.get('camera_id'))
+                            logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+            if pool._isupdate:
+                logging.info(f"鏇存柊绾跨▼寮�濮�")
+                pool.shutdown_all()
+                if camera_data:
+                    for camera in camera_data:
+                        thread = pool.threads.get(camera.get("camera_id"))
+                        if not thread:
+                            logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+                            pool.safe_start(pool.worker, camera.get('camera_id'))
+                            logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+                logging.info(f"鏇存柊绾跨▼缁撴潫")
+
+            is_init = False
+            time_sel.sleep(1)
+        except Exception as e:
+            logging.info(f"涓荤嚎绋嬫湭鐭ラ敊璇�:{e}")
diff --git a/qwen_vllm_thread.py b/qwen_vllm_thread.py
new file mode 100644
index 0000000..993b747
--- /dev/null
+++ b/qwen_vllm_thread.py
@@ -0,0 +1,91 @@
+from datetime import datetime
+import logging
+import os
+from concurrent.futures import ThreadPoolExecutor
+import threading
+from logging.handlers import RotatingFileHandler
+from langchain_openai import ChatOpenAI
+from pymilvus import connections, Collection
+import qwen_vllm
+
+
+def process_task(detect,image_id,ragurl,ragmode,max_tokens):
+    image_id = detect.tark_do(image_id,ragurl,ragmode,max_tokens)
+    print(f"瀹屾垚浠诲姟 {image_id} (鑰楁椂: {10:.2f}s)")
+    return image_id
+
+
+class qwen_vllm_thread:
+    def __init__(self, max_workers,camera_id,config):
+        self.executor = ThreadPoolExecutor(max_workers=max_workers)
+        self.semaphore = threading.Semaphore(max_workers)
+        self.max_workers = max_workers
+        # 鍒濆鍖朚ilvus闆嗗悎
+        connections.connect("default", host=config.get("milvusurl"), port=config.get("milvusport"))
+        # 鍔犺浇闆嗗悎
+        self.collection = Collection(name="smartobject")
+        self.collection.load()
+
+        # 鍒濆鍖朙angChain瀹㈡埛绔�
+        self.llm = ChatOpenAI(
+            model=config.get("vllmmode"),  # 涓�--served-model-name涓�鑷�
+            temperature=0.7,
+            max_tokens=200,
+            base_url=config.get("vllmurl"),
+            api_key="EMPTY"
+        )
+        self.config = config
+        # 鍒濆鍖�
+        self.detect = qwen_vllm.detect_tasks()
+        self.detect._thread_name = f"{camera_id}"  # 璁剧疆鍚嶇О
+        self.detect.init_logging(f"{camera_id}")
+        # 鍒濆鍖朚ilvus闆嗗悎
+        self.detect.collection = self.collection
+        self.detect.llm = self.llm
+        # 鍒涘缓瀹炰緥涓撳睘logger
+        self.logger = logging.getLogger(f"{self.__class__}_{id(self)}")
+        self.logger.setLevel(logging.INFO)
+        # 閬垮厤閲嶅娣诲姞handler
+        if not self.logger.handlers:
+            handler = RotatingFileHandler(
+                filename=os.path.join("logs", 'thread_log.log'),
+                maxBytes=10 * 1024 * 1024,
+                backupCount=3,
+                encoding='utf-8'
+            )
+            formatter = logging.Formatter(
+                '%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s'
+            )
+            handler.setFormatter(formatter)
+            self.logger.addHandler(handler)
+
+    def submit(self,res_a):
+        # 灏濊瘯鑾峰彇淇″彿閲忥紙闈為樆濉烇級
+        acquired = self.semaphore.acquire(blocking=False)
+
+        if not acquired:
+            self.logger.info(f"绾跨▼姹犲凡婊★紝绛夊緟绌洪棽绾跨▼... (褰撳墠娲昏穬: {self.max_workers - self.semaphore._value}/{self.max_workers})")
+            # 闃诲绛夊緟鐩村埌鏈夊彲鐢ㄧ嚎绋�
+            self.semaphore.acquire(blocking=True)
+
+        future = self.executor.submit(self._wrap_task, res_a)
+        future.add_done_callback(self._release_semaphore)
+        return future
+
+    def _wrap_task(self, res):
+        try:
+            #self.logger.info(f"澶勭悊: { res['id']}寮�濮�")
+            current_time = datetime.now()
+            image_id = self.detect.tark_do(res, self.config.get("ragurl"), self.config.get("ragmode"), self.config.get("max_tokens"))
+            self.logger.info(f"澶勭悊: { res['id']}瀹屾瘯{image_id}:{datetime.now() - current_time}")
+            return image_id
+        except Exception as e:
+            self.logger.info(f"浠诲姟 { res['id']} 澶勭悊鍑洪敊: {e}")
+            raise
+
+    def _release_semaphore(self, future):
+        self.semaphore.release()
+        self.logger.info(f"閲婃斁绾跨▼ (鍓╀綑绌洪棽: {self.semaphore._value}/{self.max_workers})")
+
+    def shutdown(self):
+        self.executor.shutdown()
diff --git a/smart_detecttest1111.py b/smart_detecttest1111.py
new file mode 100644
index 0000000..a2a2113
--- /dev/null
+++ b/smart_detecttest1111.py
@@ -0,0 +1,261 @@
+
+import threading
+import time as time_sel
+from typing import Dict
+
+import cv2
+import numpy as np
+
+import detect_task
+from datetime import time
+import requests
+import os
+from datetime import datetime
+import torch
+import logging
+import jieba.posseg as pseg
+from transformers import AutoModel, AutoTokenizer, AutoModelForCausalLM, AutoConfig, AutoProcessor, \
+    AutoModelForVision2Seq
+from pymilvus import connections, Collection
+from logging.handlers import RotatingFileHandler
+
+class ThreadPool:
+    def __init__(self):
+        #璇诲彇閰嶇疆鏂囦欢
+        self.config = {}
+        with open('./conf.txt', 'r', encoding='utf-8') as file:
+            for line in file:
+                # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+                line = line.strip()
+                # 璺宠繃绌鸿
+                if not line:
+                    continue
+                # 鍒嗗壊閿拰鍊�
+                if '=' in line:
+                    key, value = line.split('=', 1)
+                    # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+                    key = key.strip()
+                    value = value.strip()
+                    # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+                    self.config[key] = value
+
+        self.threads: Dict[str, threading.Thread] = {}
+        self.lock = threading.Lock()
+        # 閰嶇疆鏃ュ織
+        # 纭繚鏃ュ織鐩綍瀛樺湪
+        log_dir = "logs"
+        os.makedirs(log_dir, exist_ok=True)
+
+
+        self.device = "cuda:0" if torch.cuda.is_available() else "cpu"
+
+        # 鍒濆鍖栧悜閲忔ā鍨�
+        self.qwen_tokenizer = AutoProcessor.from_pretrained("Qwen2-VL-2B", trust_remote_code=True)
+        self.qwen_model = AutoModelForVision2Seq.from_pretrained("Qwen2-VL-2B", device_map="auto",
+                                                            trust_remote_code=True).eval()
+        # 鍒濆鍖朚ilvus闆嗗悎
+        connections.connect("default", host=self.config.get("milvusurl"), port=self.config.get("milvusport"))
+        # 鍔犺浇闆嗗悎
+        self.collection = Collection(name="smartobject")
+        self.collection.load()
+
+        # 閰嶇疆鏃ュ織
+        logging.basicConfig(
+            level=logging.INFO,
+            format='%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s',
+            datefmt='%Y-%m-%d %H:%M:%S',
+            handlers=[
+                # 鎸夊ぇ灏忚疆杞殑鏃ュ織鏂囦欢锛堟渶澶�10MB锛屼繚鐣�3涓浠斤級
+                RotatingFileHandler(
+                    filename=os.path.join(log_dir, 'start_log.log'),
+                    maxBytes=10 * 1024 * 1024,  # 10MB
+                    backupCount=3,
+                    encoding='utf-8'
+                ),
+                # 鍚屾椂杈撳嚭鍒版帶鍒跺彴
+                logging.StreamHandler()
+            ]
+        )
+
+    def cross_collection_vector_compare(self,image_id,video_point_id,rule_id,video_image_time,frame_id,task_id,video_path,videotaskurl):
+        try:
+            # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+            res_a = self.collection.query(
+                expr=f"id in {image_id}",
+                output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "object_label", "task_id", "event_level_id",
+                               "video_point_id", "detect_num", "detect_id", "detect_time", "image_path", "video_path"],
+                consistency_level="Strong"
+            )
+
+            # 2. 浠庨泦鍚圔鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+            res_b = self.collection_rule.query(
+                expr=f"rule_id in {rule_id}",
+                output_fields=["id", "zh_desc_class", "text_vector","range_value"],
+                consistency_level="Strong"
+            )
+
+            # 3. 璁$畻涓や袱鐩镐技搴�
+            results = []
+            pos_weights = {
+                ('n', 'n'): 1.0,  # 鍚嶈瘝鍖归厤
+                ('v', 'v'): 0.8,  # 鍔ㄨ瘝鍖归厤
+                ('n', 'v'): 0.3  # 鍚嶈瘝-鍔ㄨ瘝浜ゅ弶
+            }
+            # 寰幆缁撴灉闆�
+            for item_a in res_a:
+                if item_a["detect_num"]>0 : # 鏈夋娴嬪埌鐩爣鏃惰繘琛屾瘮瀵�
+                    for item_b in res_b: # 鍜屾瘡涓鍒欓」杩涜瀵规瘮
+                        similarity = 0
+                        # 1. 鍚戦噺鐩镐技搴︼紙60%鏉冮噸锛�
+                        # 灏嗗悜閲忚浆涓簄umpy鏁扮粍
+                        vec_a = np.array(item_a["text_vector"])
+                        vec_b = np.array(item_b["text_vector"])
+                        assert vec_a.shape == vec_b.shape, f"缁村害涓嶅尮閰�: {vec_a.shape} vs {vec_b.shape}"
+                        vec_a = vec_a.astype(np.float64)  # 鎻愬崌璁$畻绮惧害
+                        vec_b = vec_b.astype(np.float64)
+                        # 璁$畻鐩镐技搴�
+                        vector_sim = np.dot(vec_a, vec_b) / (np.linalg.norm(vec_a) * np.linalg.norm(vec_b))
+
+                        # 2. 璇嶆�у尮閰嶅害锛�40%鏉冮噸锛�
+                        desc_a = ast.literal_eval(item_a['zh_desc_class'])  # 鑾峰彇鐩爣璇箟
+                        desc_b = ast.literal_eval(item_b['zh_desc_class'])
+                        for clas_a in desc_a:   # 鍜屾瘡涓洰鏍囪涔夎繘琛屽姣�
+                            pos_match = 0
+                            for (_, pos_a, _), (_, pos_b, _) in zip(clas_a, desc_b):
+                                pos_match += pos_weights.get((pos_a, pos_b), 0)
+                            pos_match /= max(len(clas_a), len(desc_b))
+
+                            #鎸夋潈閲嶇粍瑁� 褰撳墠鐩镐技搴� 骞惰祴鍊兼渶澶у��
+                            stem_int = 0.6 * vector_sim + 0.4 * pos_match
+                            if stem_int > similarity:
+                                similarity = stem_int
+
+                        # 3.鐩镐技搴﹀鏋滃ぇ浜庤鍒欏尮閰嶉槇鍊�,缁勮棰勮鏁版嵁
+                        if similarity > item_b["range_value"]:
+                            logging.info(f"鐩镐技搴︼細{similarity}锛歿item_a['zh_desc_class']} {item_b['zh_desc_class']}")
+                            results.append({
+                                "a_id": item_a["id"],
+                                "b_id": item_b["id"],
+                                "similarity": round(float(similarity), 4)
+                            })
+
+            # 4. 鎸夌浉浼煎害鎺掑簭
+            if len(results) > 0:
+                comparison_results = sorted(results, key=lambda x: x["similarity"], reverse=True) # 闆嗗悎鎺掑簭
+                # 淇濆瓨褰曞儚瑙嗛
+                asyncio.run(self.video_task(video_point_id,video_image_time,"basic",frame_id,video_path,videotaskurl))
+                # 淇濆瓨鍒癿ilvus
+                self.update_milvus(image_id,res_a,1,comparison_results[0]['similarity'],rule_id)
+            else:
+                self.update_milvus(image_id,res_a,0,0.0,rule_id)
+        except Exception as e:
+            self.logger.info(f"{video_point_id}绾跨▼锛氳鍒欏姣旀椂鍑洪敊:{image_id,rule_id}锛� {e}")
+
+    #鍚姩褰曞儚
+    async def video_task(self,video_point_id,video_image_time,task_id,frame_id,video_path,videotaskurl):
+        try:
+            json_data = {
+                "cameraId": f"{video_point_id}",
+                "timestamp": video_image_time,
+                "preSeconds": 10,
+                "postSeconds": 10,
+                "taskId": task_id,
+                "fid": frame_id,
+                "uploadUrl": video_path,
+                "uploadType": "local"
+            }
+            self.logger.info(f"{video_point_id}绾跨▼锛氳皟鐢ㄥ綍鍍忔湇鍔�:{videotaskurl, json_data}")
+
+            # 瀹氫箟璇锋眰鐨� URL
+            # 鍙戦�� GET 璇锋眰
+            response = requests.post(videotaskurl,json=json_data,timeout=(0.03, 0.03))
+            # 妫�鏌ュ搷搴旂姸鎬佺爜
+            if response.status_code == 200:
+                data = response.json()
+                print(data)
+        except Exception as e:
+            self.logger.info(f"{self._thread_name}绾跨▼锛氳皟鐢ㄥ綍鍍忔椂鍑洪敊:鍦板潃锛歿videotaskurl}锛歿e}")
+
+    def update_milvus(self,image_id,res_a,is_waning,similarity,rule_id_list):
+        try:
+            # 淇濆瓨鍒癿ilvus
+            self.collection.upsert(
+                data=[{
+                    "id": image_id[0],
+                    "text_vector": res_a[0]["text_vector"],
+                    "is_waning": is_waning,
+                    "waning_value": similarity,
+                    "rule_id": rule_id_list,
+                    "zh_desc_class": res_a[0]['zh_desc_class'],  # text_vector
+                    "bounding_box": res_a[0]['bounding_box'],  # bounding_box
+                    "object_label": res_a[0]['object_label'],  # desc
+                    "task_id": res_a[0]['task_id'],  # task_id
+                    "event_level_id": res_a[0]['event_level_id'],  # event_level_id
+                    "video_point_id": res_a[0]['video_point_id'],  # video_point_id
+                    "detect_num": res_a[0]['detect_num'],
+                    "detect_id": res_a[0]['detect_id'],  # detect_id
+                    "detect_time": res_a[0]['detect_time'],  # detect_time
+                    "image_path": res_a[0]['image_path'],  # image_path
+                    "video_path": res_a[0]['video_path']  # video_path
+                }]
+            )
+        except Exception as e:
+            self.logger.info(f"{self._thread_name}绾跨▼锛氳鍒欏姣斿悗淇敼鏁版嵁鏃跺嚭閿�:{image_id}锛氭槸鍚﹂璀is_waning}锛氶璀﹀�硷細{similarity}锛氳鍒檌d:{rule_id_list}:鏁版嵁闆嗗悎锛歿len(res_a)} :{e}")
+
+    def tark_do():
+        try :
+            # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+            res_a = collection.query(
+                expr=f"id == {image_id}",
+                output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "object_label", "task_id", "event_level_id",
+                               "video_point_id", "detect_num", "is_waning", "waning_value",  "rule_id", "detect_id", "detect_time", "image_path", "video_path"],
+                consistency_level="Strong"
+            )
+            # 鍥剧墖鍜岃棰戝湴鍧�
+            image = Image.open(image_path)  # 鏇挎崲涓烘偍鐨勫浘鐗囪矾寰�
+            image = image.thumbnail((512, 512))
+            text = "鎻忚堪杩欏紶鍥剧墖鐨勫唴瀹�"
+            # 澶勭悊杈撳叆
+            inputs = qwen_tokenizer(text=text, images=image, return_tensors="pt").to("cuda")
+            # 鐢熸垚杈撳嚭
+            with torch.no_grad():
+                outputs = qwen_model.generate(**inputs, max_new_tokens=50)
+            response = qwen_tokenizer.decode(outputs[0], skip_special_tokens=True)
+            print(response)
+
+            # 淇濆瓨鍒癿ilvus
+            collection.upsert(
+                data=[{
+                    "id": image_id,
+                    "text_vector": res_a[0]["text_vector"],
+                    "is_waning": res_a[0]["is_waning"],
+                    "waning_value": res_a[0]["waning_value"],
+                    "rule_id": res_a[0]["rule_id"],
+                    "zh_desc_class": res_a[0]['zh_desc_class'],  # text_vector
+                    "bounding_box": res_a[0]['bounding_box'],  # bounding_box
+                    "object_label": f"{response}",  # desc
+                    "task_id": res_a[0]['task_id'],  # task_id
+                    "event_level_id": res_a[0]['event_level_id'],  # event_level_id
+                    "video_point_id": res_a[0]['video_point_id'],  # video_point_id
+                    "detect_num": res_a[0]['detect_num'],
+                    "detect_id": res_a[0]['detect_id'],  # detect_id
+                    "detect_time": res_a[0]['detect_time'],  # detect_time
+                    "image_path": res_a[0]['image_path'],  # image_path
+                    "video_path": res_a[0]['video_path']  # video_path
+                }]
+            )
+            print(f"鎵ц浠诲姟{image_id,image_path}锛氱粨鏉�")
+            return 1
+        except Exception as e:
+            print(f"鎵ц妯″瀷瑙f瀽鏃跺嚭閿�:{image_id,image_path} :{e}")
+            return 0
+
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+    pool = ThreadPool()
+    while True:
+        try:
+            pool.tark_do()
+        except Exception as e:
+            logging.info(f"涓荤嚎绋嬫湭鐭ラ敊璇�:{e}")
diff --git a/temp.jpg b/temp.jpg
new file mode 100644
index 0000000..2841ca1
--- /dev/null
+++ b/temp.jpg
Binary files differ
diff --git a/vllm.py b/vllm.py
new file mode 100644
index 0000000..bb4814f
--- /dev/null
+++ b/vllm.py
@@ -0,0 +1,62 @@
+import torch
+from modelscope import Qwen2_5_VLForConditionalGeneration, AutoTokenizer, AutoProcessor
+from qwen_vl_utils import process_vision_info
+
+# default: Load the model on the available device(s)
+model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
+    "Qwen2.5-VL-3B-Instruct-AWQ", torch_dtype=torch.float16, device_map="auto"
+)
+
+# We recommend enabling flash_attention_2 for better acceleration and memory saving, especially in multi-image and video scenarios.
+# model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
+#     "Qwen/Qwen2.5-VL-3B-Instruct-AWQ",
+#     torch_dtype=torch.bfloat16,
+#     attn_implementation="flash_attention_2",
+#     device_map="auto",
+# )
+
+# default processer
+processor = AutoProcessor.from_pretrained("Qwen2.5-VL-3B-Instruct-AWQ")
+
+# The default range for the number of visual tokens per image in the model is 4-16384.
+# You can set min_pixels and max_pixels according to your needs, such as a token range of 256-1280, to balance performance and cost.
+# min_pixels = 256*28*28
+# max_pixels = 1280*28*28
+# processor = AutoProcessor.from_pretrained("Qwen/Qwen2.5-VL-3B-Instruct-AWQ", min_pixels=min_pixels, max_pixels=max_pixels)
+
+messages = [
+    {
+        "role": "user",
+        "content": [
+            {
+                "type": "image",
+                "image": "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg",
+            },
+            {"type": "text", "text": "Describe this image."},
+        ],
+    }
+]
+
+# Preparation for inference
+text = processor.apply_chat_template(
+    messages, tokenize=False, add_generation_prompt=True
+)
+image_inputs, video_inputs = process_vision_info(messages)
+inputs = processor(
+    text=[text],
+    images=image_inputs,
+    videos=video_inputs,
+    padding=True,
+    return_tensors="pt",
+)
+inputs = inputs.to("cuda")
+
+# Inference: Generation of the output
+generated_ids = model.generate(**inputs, max_new_tokens=128)
+generated_ids_trimmed = [
+    out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
+]
+output_text = processor.batch_decode(
+    generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
+)
+print(output_text)
\ No newline at end of file

--
Gitblit v1.8.0