Compare commits

...

No commits in common. 'd263f800d3c67c306e956891216383ebd8e6ed07' and '54f55899d62d9b88c218f62e2329c38f084a80cb' have entirely different histories.

163
.gitignore vendored

@ -0,0 +1,163 @@
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/

@ -1,9 +0,0 @@
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@ -0,0 +1,35 @@
[base]
# 向量库相似度阈值
similarity_threshold = 0.93
# 模型供应商
model_form = 'siliconflow'
[siliconflow]
# 硅基流动
# 密钥
api_key = 'sk-rdoyeoxcyvqjynufqjmewmipwtvrhjjzerqlinpqxiodyafp'
# 模型名称
model = 'Qwen/QwQ-32B'
# API地址
base_url = 'https://api.siliconflow.cn/v1/'
# 最大token数
max_tokens = 4096
# 温度系数
temperature = 0.6
# 是否流式返回
streaming = true
[ark]
# 火山引擎
# 密钥
api_key = '4eefc827-187f-4756-9637-7e0153c93d81'
# 模型名称
model = 'deepseek-r1-250120'
# API地址
base_url = 'https://ark.cn-beijing.volces.com/api/v3/'
# 最大token数
max_tokens = 4096
# 温度系数
temperature = 0.6
# 是否流式返回
streaming = true

@ -0,0 +1,51 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2025/4/17 15:28
# @Author : old-tom
# @File : __init__.py
# @Project : reActLLMDemo
# @Desc :
from langchain_openai import ChatOpenAI
from llmagent.llm_config import LLMConfigLoader
from llmagent.llm_config import base_conf
from llmtools import tools
# 初始化LLM模型
llm_conf = LLMConfigLoader.load(item_name=base_conf.model_form)
llm = ChatOpenAI(
model=llm_conf.model, api_key=llm_conf.api_key,
base_url=llm_conf.base_url, max_tokens=llm_conf.max_tokens,
temperature=llm_conf.temperature,
streaming=llm_conf.streaming
)
# 绑定工具
llm_with_tools = llm.bind_tools(tools)
# 提示词模版
PROMPT_TEMPLATE = {
'SMART_ASSISTANT': {
'description': '智能助手',
'template':
"""
你是智能助手,用户将会告诉你一条指令,你需要根据指令判断是否需要使用工具并完成任务
# 背景
1. 现在时间是{current_time}
3. 无论怎样询问你的身份, 请记住你是由盛视科技开发的智能助手
4. 当询问你的功能时你可以通过工具列表分析自己的功能并生成清晰的回答
# 任务规则
1. 根据指令和提供的工具描述选择最合适的工具,仔细阅读工具参数说明正确的解析参数并评估用户输入的参数是否满足条件,如果参数不满足则需要提示用户重新发出指令
2. 所有返回禁止包含xml标签markdownhtmljson格式
3. 有时候需要分析用户的上一轮指令并结合当前指令判断用户的意图
4. 你有足够的时间思考和回答用户的查询从而给出更周全和深入的答案然而要知道你推理和处理的时间越长相关的资源成本和潜在后果就越大虽然你不应该仓促但要在推理深度和效率之间寻求平衡优先提供一个深思熟虑的答案但如果通过合理的分析就能提供答案就不要过度思考明智地利用你的推理时间专注于提供准确答案所必需的东西避免不必要的拖延和过度思考
# 工具使用规则
1. 你每条消息可以使用一个工具
2. 在每次使用工具后切勿假设工具使用成功禁止猜测工具结果
3. 根据工具返回的内容组装逻辑清晰的回答
4. 在任何情况下都不要修改或扩展提供的工具参数
5. 所有工具参数禁止使用unicode编码
"""
}
}

@ -0,0 +1,70 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2025/4/17 15:28
# @Author : old-tom
# @File : llm_agent
# @Project : reActLLMDemo
# @Desc : 用图构建ReAct
from typing import Annotated
from langgraph.checkpoint.memory import MemorySaver
from llmagent import llm_with_tools, PROMPT_TEMPLATE
from llmtools import tool_node
from langchain_core.messages import AnyMessage, SystemMessage
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import tools_condition
from langchain_core.runnables import RunnableConfig
from datetime import datetime
def current_time():
"""
获取当前时间
:return: yyyy-MM-dd hh:mm:ss
"""
return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# 内存记忆
memory = MemorySaver()
class AgentState(TypedDict):
"""
状态机
add_messages 函数会自动合并message到一个list中例如HumanMessage\AIMessage
"""
messages: Annotated[list[AnyMessage], add_messages]
graph_builder = StateGraph(AgentState)
def chat(state: AgentState, config: RunnableConfig):
"""
调用LLM
:param state: 状态机
:param config: 配置
LLM需要从状态机获取message
:return:
"""
# 设置系统提示词
system_prompt = SystemMessage(PROMPT_TEMPLATE['SMART_ASSISTANT']['template'].format(current_time=current_time()))
return {"messages": [llm_with_tools.invoke([system_prompt] + state["messages"], config)]}
# 以下步骤可以替换为预构建的create_react_agent函数
# LLM节点
graph_builder.add_node("chat_llm", chat)
# 工具节点
graph_builder.add_node("tools", tool_node)
graph_builder.add_edge(START, "chat_llm")
graph_builder.add_edge("chat_llm", END)
# 添加条件边tools_condition 是官方实现的函数用于判断是否应该调用tool或者直接结束
graph_builder.add_conditional_edges("chat_llm", tools_condition)
graph_builder.add_edge("tools", "chat_llm")
# checkpointer 是检查点设置
graph = graph_builder.compile(name='smart_assistant', checkpointer=memory)

@ -0,0 +1,63 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2025/4/17 15:28
# @Author : old-tom
# @File : llm_config
# @Project : reActLLMDemo
# @Desc : llm配置文件解析
import os
from pydantic import BaseModel
import toml
# 默认配置文件名
DEFAULT_CONF_NAME = 'env.toml'
path = os.path.dirname(__file__)
path = os.path.dirname(path)
# 默认配置文件位置
DEFAULT_CONF_PATH = os.path.join(path, DEFAULT_CONF_NAME)
class ConfigNotFoundError(Exception):
"""
配置不存在异常
"""
def __init__(self, msg):
Exception.__init__(self, msg)
def load_env():
if not os.path.isfile(DEFAULT_CONF_PATH):
raise ConfigNotFoundError(f'模型配置文件{DEFAULT_CONF_NAME}不存在')
return toml.load(DEFAULT_CONF_PATH)
conf = load_env()
class LLMConf(BaseModel):
api_key: str
model: str
base_url: str
max_tokens: int
temperature: float
streaming: bool = True
class LLMConfigLoader(object):
@staticmethod
def load(item_name) -> LLMConf:
"""
校验并加载配置
:return:
"""
return LLMConf(**conf[item_name])
class BaseConf(BaseModel):
similarity_threshold: float
model_form: str
base_conf = BaseConf(**conf['base'])

@ -0,0 +1,14 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2025/4/17 15:40
# @Author : old-tom
# @File : __init__.py
# @Project : reActLLMDemo
# @Desc :
from llmtools.tool_impl import play_video, split_screen, play_video_record, switch_page, zoom_in, view_flight_details
from langgraph.prebuilt import ToolNode
# 工具列表
tools = [play_video, split_screen, play_video_record, switch_page, zoom_in, view_flight_details]
# 工具节点ToolNode 内置了工具调用函数及异常处理
tool_node = ToolNode(tools=tools)

@ -0,0 +1,84 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2025/4/12 14:55
# @Author : old-tom
# @File : tool_impl
# @Project : sttFunctionCallBackend
# @Desc : 工具定义
from typing import Annotated
from langchain_core.tools import tool
from vector_db import query_vector_db
from log_conf import log
from llmagent.llm_config import base_conf
@tool("play_video", description="播放、查看、打开实时视频")
def play_video(camera_name: Annotated[str, "相机名称,例如南卡口1号相机"]) -> str:
camera_info = query_camera_from_db(camera_name)
log.info('【function】play_video 输入 [{}],向量库返回{}', camera_name, camera_info)
if camera_info:
if len(camera_info) > 1:
hit_camera_names = [x['carme_name'] for x in camera_info]
return f"【tool_back】找到以下相机请选择一个{hit_camera_names}"
else:
# TODO 调用业务系统
return f"【tool_back】正在打开{camera_name},请等待操作完成"
else:
return "【tool_back】未找到该相机,请尝试其他名称"
@tool("split_screen", description="切换分屏")
def split_screen(split_n: Annotated[int, "要切换的分屏数量,整数并且大于0例如1分屏、2分屏。如果是中文,例如:壹、贰、参需要转为数字形式"]) -> str:
return f"【tool_back】正在切换到{split_n}分屏,请等待操作完成"
@tool("play_video_record", description="播放、打开录像")
def play_video_record(camera_name: Annotated[str, "相机名称,例如南卡口1号相机,如果没有提供时间,结束时间为当前时间,开始时间为当前时间往前5分钟"],
start_time: Annotated[str, "录像开始时间,格式为yyyy-MM-dd hh:mm:ss例 2025-03-16 01:00:00"],
end_time: Annotated[str, "录像结束时间,格式为yyyy-MM-dd hh:mm:ss例 2025-03-16 02:09:31"]) -> str:
log.info('【function】play_video_record 输入 [{},{},{}]', camera_name, start_time, end_time)
return f"【tool_back】正在打开{camera_name}的录像,请等待操作完成"
@tool("switch_page", description="打开、跳转页面")
def switch_page(page_name: Annotated[str, "页面中文名称或者缩写,例:人员核查、系统日志、设备管理、首页"]) -> str:
log.info('【function】switch_page 输入 [{}]', page_name)
return f"【tool_back】正在打开{page_name},请等待操作完成"
@tool("zoom_in", description="放大电子地图")
def zoom_in(level_n: Annotated[int, "放大等级,整数并且大于0小于5例如放大1级、放大2级"]) -> str:
log.info('【function】zoom_in 输入 [{}]', level_n)
return f"【tool_back】正在放大电子地图至{level_n}级,请等待操作完成"
@tool("view_flight_details", description="查询指定机场指定航班及时间的出入境人员明细")
def view_flight_details(
airport_name: Annotated[str, "机场名称,简体中文,可以是缩写,例如:成都天府机场、天府机场、长水机场、上海浦东机场"],
flight_code: Annotated[
str, "航班编号,由字母+数字组成的完整编号,若编号包含多余字符(如标点符号),需过滤后保留有效部分"],
flight_date: Annotated[str, "提取完整日期(年月日),自动补零至标准格式 yyyy-MM-dd, 例2025-03-16"],
ie_type: Annotated[str, "出入境类型,仅识别'入境''出境'两种类型"]) -> str:
log.info('【function】view_flight_details 输入 [{},{},{},{}]', airport_name, flight_code, flight_date, ie_type)
return f"【tool_back】{airport_name}航班号{flight_code}{flight_date}{ie_type}数据,共100人乘机,起飞准时,晚点降落"
def query_camera_from_db(camera_name: str, top_n: int = 3) -> str:
"""
相机名称查询向量库,根据相似度阈值取top_one或者top_n
:param camera_name: 相机名称
:param top_n: 返回前N个
:return:
"""
rt = query_vector_db(camera_name)
if rt:
log.info('【function】相机相似度检索查询[{}],返回 {}', camera_name, rt)
# 判断相似度最高的相机是否超过阈值
top_one = rt['hits'][0]
# 相似度评分
score = top_one['_score']
if score > base_conf.similarity_threshold:
return rt['hits'][0:1]
else:
return rt['hits'][0:top_n]

@ -0,0 +1,38 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2025/4/19 18:27
# @Author : old-tom
# @File : local_test
# @Project : reActLLMDemo
# @Desc : 本地终端运行对话
from llmagent.assistant_graph import graph
def stream_graph_updates(user_input: str):
"""
流式输出
:param user_input:
:return:
"""
config = {"configurable": {"thread_id": "1"}}
for chunk, metadata in graph.stream({"messages": [{"role": "user", "content": user_input}]}, config,
stream_mode='messages'):
if chunk.content:
print(chunk.content, end='', flush=True)
print('\n')
if __name__ == '__main__':
while True:
try:
user_input = input("User: ")
if user_input.lower() in ["quit", "exit", "q"]:
print("Goodbye!")
break
stream_graph_updates(user_input)
except Exception as e:
user_input = f"出错了,系统提示{e}"
print("User: " + user_input)
stream_graph_updates(user_input)
break

@ -0,0 +1,44 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2025/4/12 14:51
# @Author : old-tom
# @File : log_conf
# @Project : sttFunctionCallBackend
# @Desc :
import sys
import os
from loguru import logger
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
# 日志输出路径
LOG_PATH = os.path.join(BASE_DIR, r'logout/logout.log')
class Logger(object):
def __init__(self):
self.logger = logger
self.logger.remove()
self.logger.add(sys.stdout,
format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | " # 颜色>时间
"{process.name} | " # 进程名
"{thread.name} | " # 进程名
"<cyan>{module}</cyan>.<cyan>{function}</cyan>" # 模块名.方法名
":<cyan>{line}</cyan> | " # 行号
"<level>{level}</level>: " # 等级
"<level>{message}</level>", # 日志内容
)
# 输出到文件的格式,注释下面的add',则关闭日志写入
self.logger.add(LOG_PATH, level='DEBUG',
format='{time:YYYY-MM-DD HH:mm:ss} - ' # 时间
"{process.name} | " # 进程名
"{thread.name} | " # 进程名
'{module}.{function}:{line} - {level} -{message}', # 模块名.方法名:行号
rotation="10 MB")
def get_logger(self):
return self.logger
log = Logger().get_logger()

@ -0,0 +1,19 @@
[project]
name = "reactllmdemo"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"langchain-community>=0.3.21",
"langchain-openai>=0.3.13",
"langgraph>=0.3.30",
"loguru>=0.7.3",
"marqo>=3.12.0",
"toml>=0.10.2",
]
[[tool.uv.index]]
name = "private-pypi"
url = "https://mirrors.aliyun.com/pypi/simple/"
default = true

@ -0,0 +1,14 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2025/4/19 18:27
# @Author : old-tom
# @File : local_test
# @Project : reActLLMDemo
# @Desc : 作为服务端运行
def main():
print("Hello from reactllmdemo!")
if __name__ == "__main__":
main()

1343
uv.lock

File diff suppressed because it is too large Load Diff

@ -0,0 +1,633 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2025/3/16 20:09
# @Author : old-tom
# @File : vector_agent
# @Project : llmFunctionCallDemo
# @Desc : 向量数据库,解决相似度查询,例如 相机名称
import marqo
# 索引名称
INDEX_NAME = 'camera_collection'
# 初始化marqo
mq = marqo.Client(url='http://171.92.0.3:8882')
# mq.delete_index(INDEX_NAME)
#
# settings = {
# "treatUrlsAndPointersAsImages": False,
# "model": "hf/bge-large-zh-v1.5",
# "normalizeEmbeddings": True,
# }
def create_and_set_index():
"""
全局只能调用一次
:return:
"""
mq.create_index(INDEX_NAME, model='hf/e5-base-v2')
# mq.create_index(INDEX_NAME, settings_dict=settings)
# 添加文档(测试用)
mq.index(INDEX_NAME).add_documents([
{
"carme_name": "中方国门AI算法",
"ip": "192.168.10.80",
"location": "国门顶部"
},
{
"carme_name": "中方国门AI算法0102",
"ip": "192.168.10.80",
"location": "国门顶部"
},
{
"carme_name": "中方国门入境1",
"ip": "192.168.10.77",
"location": "国门通道"
},
{
"carme_name": "中方国门入境2",
"ip": "192.168.10.79",
"location": "国门通道"
},
{
"carme_name": "中方国门入境摄像头中",
"ip": "192.168.10.72",
"location": "登临检验"
},
{
"carme_name": "中方国门入境摄像头右",
"ip": "192.168.10.74",
"location": "登临检验"
},
{
"carme_name": "中方国门入境摄像头左",
"ip": "192.168.10.75",
"location": "登临检验"
},
{
"carme_name": "中方国门出境1",
"ip": "192.168.10.76",
"location": "国门通道"
},
{
"carme_name": "中方国门出境2",
"ip": "192.168.10.78",
"location": "国门通道"
},
{
"carme_name": "中方国门出境摄像头右",
"ip": "192.168.10.71",
"location": "登临检验"
},
{
"carme_name": "中方国门出境摄像头左",
"ip": "192.168.10.73",
"location": "登临检验"
},
{
"carme_name": "中方国门-面向国门球机",
"ip": "192.168.10.215",
"location": "国门通道拐角"
},
{
"carme_name": "中方国门高点1",
"ip": "192.168.10.70",
"location": "国门顶部"
},
{
"carme_name": "北卡口AI摄像头全景",
"ip": "192.168.10.30",
"location": "北卡口对面"
},
{
"carme_name": "北卡口AI摄像头细节",
"ip": "192.168.10.30",
"location": "北卡口对面"
},
{
"carme_name": "北卡口入境摄像头入场4号通道",
"ip": "192.168.10.112",
"location": "入场通道"
},
{
"carme_name": "北卡口入境摄像头入场5号通道",
"ip": "192.168.10.114",
"location": "入场通道"
},
{
"carme_name": "北卡口入境摄像头入场6号通道",
"ip": "192.168.10.117",
"location": "入场通道"
},
{
"carme_name": "北卡口入境摄像头出场1号通道",
"ip": "192.168.10.115",
"location": "出场通道"
},
{
"carme_name": "北卡口入境摄像头出场2号通道",
"ip": "192.168.10.116",
"location": "出场通道"
},
{
"carme_name": "北卡口入境摄像头出场3号通道",
"ip": "192.168.10.113",
"location": "出场通道"
},
{
"carme_name": "北卡口出口道路监控",
"ip": "192.168.10.153",
"location": "路口"
},
{
"carme_name": "能投大厦高点1",
"ip": "192.168.10.89",
"location": "能投楼顶"
},
{
"carme_name": "南卡口AI算法2",
"ip": "192.168.10.210",
"location": "南卡口顶部"
},
{
"carme_name": "南卡口AI算法20102",
"ip": "192.168.10.210",
"location": "南卡口顶部"
},
{
"carme_name": "南卡口AI算法识别摄像机",
"ip": "192.168.10.91",
"location": "南卡口顶部"
},
{
"carme_name": "南卡口AI算法识别摄像机0102",
"ip": "192.168.10.91",
"location": "南卡口顶部"
},
{
"carme_name": "南卡口出境摄像头1号通道",
"ip": "192.168.10.100",
"location": "出境通道"
},
{
"carme_name": "南卡口出境摄像头2号通道",
"ip": "192.168.10.103",
"location": "出境通道"
},
{
"carme_name": "南卡口出境摄像头3号通道",
"ip": "192.168.10.104",
"location": "出境通道"
},
{
"carme_name": "南卡口出境摄像头4号通道",
"ip": "192.168.10.102",
"location": "出境通道"
},
{
"carme_name": "南卡口出境摄像头5号通道",
"ip": "192.168.10.99",
"location": "出境通道"
},
{
"carme_name": "南卡口出境摄像头6号通道",
"ip": "192.168.10.101",
"location": "出境通道"
},
{
"carme_name": "南卡口入境摄像头7号通道",
"ip": "192.168.10.98",
"location": "入境通道"
},
{
"carme_name": "南卡口入境摄像头8号通道",
"ip": "192.168.10.93",
"location": "入境通道"
},
{
"carme_name": "南卡口入境摄像头9号通道",
"ip": "192.168.10.97",
"location": "入境通道"
},
{
"carme_name": "南卡口入境摄像头10号通道",
"ip": "192.168.10.96",
"location": "入境通道"
},
{
"carme_name": "南卡口入境摄像头11号通道",
"ip": "192.168.10.94",
"location": "入境通道"
},
{
"carme_name": "南卡口入境摄像头12号通道",
"ip": "192.168.10.95",
"location": "入境通道"
},
{
"carme_name": "南卡口高点-1",
"ip": "192.168.10.90",
"location": "南卡口顶部"
},
{
"carme_name": "南卡口高点-2",
"ip": "192.168.10.92",
"location": "南卡口顶部"
},
{
"carme_name": "南卡口高点-3",
"ip": "192.168.3.12",
"location": "南卡口顶部"
},
{
"carme_name": "1.3公里封闭道路入境出场1",
"ip": "192.168.10.82",
"location": "南卡口顶部"
},
{
"carme_name": "1.3公里封闭道路入境出场2",
"ip": "192.168.10.88",
"location": "南卡口顶部"
},
{
"carme_name": "1.3公里封闭道路入境出场20102",
"ip": "192.168.10.88",
"location": "南卡口顶部"
},
{
"carme_name": "1.3公里封闭道路入境摄像头入场2",
"ip": "192.168.10.87",
"location": "南卡口顶部"
},
{
"carme_name": "1.3公里封闭道路入境摄像头入场20102",
"ip": "192.168.10.87",
"location": "南卡口顶部"
},
{
"carme_name": "1.3公里封闭道路入境入场1",
"ip": "192.168.10.81",
"location": "南卡口顶部"
},
{
"carme_name": "H9861号口摄像头入场",
"ip": "192.168.10.107",
"location": "H986停车场出入口"
},
{
"carme_name": "H9862号口摄像头出场",
"ip": "192.168.10.109",
"location": "H987停车场出入口"
},
{
"carme_name": "H9862号口摄像头入场",
"ip": "192.168.10.190",
"location": "H988停车场出入口"
},
{
"carme_name": "车辆定位AI摄像头",
"ip": "192.168.10.29",
"location": "H988停车场山上"
},
{
"carme_name": "车辆定位AI摄像头0102",
"ip": "192.168.10.29",
"location": "H989停车场山上"
},
{
"carme_name": "北山货场森林公园制高点",
"ip": "192.168.10.191",
"location": "H990停车场山上"
},
{
"carme_name": "边民互市入境摄像头出场",
"ip": "192.168.10.119",
"location": "边民互市"
},
{
"carme_name": "边民互市入境摄像头入场",
"ip": "192.168.10.118",
"location": "出入口"
},
{
"carme_name": "车辆缓冲区1号门入口",
"ip": "192.168.10.193",
"location": "出入口"
},
{
"carme_name": "车辆缓冲区2号门入口",
"ip": "192.168.10.195",
"location": "出入口"
},
{
"carme_name": "车辆缓冲区2号门出口",
"ip": "192.168.10.194",
"location": "出入口"
},
{
"carme_name": "车辆缓冲区1号门出口",
"ip": "192.168.10.192",
"location": "出入口"
},
{
"carme_name": "大贸查验场进口入境摄像头入场东口",
"ip": "192.168.10.181",
"location": "出入口"
},
{
"carme_name": "大贸查验场进口入境摄像头出场东口",
"ip": "192.168.10.180",
"location": "出入口"
},
{
"carme_name": "大贸查验场(进口)入境摄像头入场(西口)",
"ip": "192.168.10.106",
"location": "出入口"
},
{
"carme_name": "大贸查验场进口高点1",
"ip": "192.168.10.156",
"location": "高点"
},
{
"carme_name": "大贸查验场出口出境摄像头出场2",
"ip": "192.168.10.110",
"location": "出入口"
},
{
"carme_name": "大贸查验场出口出境摄像头入场左",
"ip": "192.168.10.184",
"location": "出入口"
},
{
"carme_name": "大贸查验场出口出境摄像头出场1",
"ip": "192.168.10.111",
"location": "出入口"
},
{
"carme_name": "北山高速收费站入境摄像头入场出方向",
"ip": "192.168.10.170",
"location": "道路"
},
{
"carme_name": "北山高速收费站入境摄像头入场入方向",
"ip": "192.168.10.169",
"location": "道路"
},
{
"carme_name": "坝洒高点",
"ip": "192.168.10.164",
"location": ""
},
{
"carme_name": "停车场卡口(坝洒)入境摄像头入场",
"ip": "192.168.10.165",
"location": "出入口"
},
{
"carme_name": "停车场卡口(坝洒)入境摄像头出场",
"ip": "192.168.10.166",
"location": "出入口"
},
{
"carme_name": "东西干道卡口入境摄像头入场",
"ip": "192.168.10.136",
"location": "出入口"
},
{
"carme_name": "东西干道卡口入境摄像头出场",
"ip": "192.168.10.135",
"location": "出入口"
},
{
"carme_name": "主卡口(临时)货场大门-高点",
"ip": "192.168.10.146",
"location": ""
},
{
"carme_name": "利丰酒店往边民互市高点",
"ip": "192.168.10.211",
"location": "利丰酒店楼顶"
},
{
"carme_name": "利丰货场近御峰货场入境摄像头出场2",
"ip": "192.168.10.132",
"location": "出入口"
},
{
"carme_name": "利丰酒店往边民互市高点2",
"ip": "192.168.10.212",
"location": "利丰酒店楼顶"
},
{
"carme_name": "利丰货场近御峰货场入境摄像头入场2",
"ip": "192.168.10.139",
"location": "出入口"
},
{
"carme_name": "利丰货场入境摄像头出场左",
"ip": "192.168.10.127",
"location": "出入口"
},
{
"carme_name": "利丰货场入境摄像头入场左",
"ip": "192.168.10.128",
"location": "出入口"
},
{
"carme_name": "利丰货场入境摄像头出场右",
"ip": "192.168.10.126",
"location": "出入口"
},
{
"carme_name": "利丰货场-高点",
"ip": "192.168.10.125",
"location": ""
},
{
"carme_name": "利丰货场近御峰货场入境摄像头出场1",
"ip": "192.168.10.131",
"location": "出入口"
},
{
"carme_name": "利丰货场入境摄像头入场右",
"ip": "192.168.10.129",
"location": "出入口"
},
{
"carme_name": "利丰货场近御峰货场入境摄像头入场1",
"ip": "192.168.10.130",
"location": "出入口"
},
{
"carme_name": "南屏高速收费站入境摄像头出场",
"ip": "192.168.10.168",
"location": "道路"
},
{
"carme_name": "南屏高速收费站入境摄像头入场",
"ip": "192.168.10.167",
"location": "道路"
},
{
"carme_name": "停车场卡口老表入境摄像头入场",
"ip": "192.168.10.160",
"location": "出入口"
},
{
"carme_name": "停车场卡口老表右入境摄像头入场",
"ip": "192.168.10.162",
"location": "出入口"
},
{
"carme_name": "停车场卡口老表入境摄像头出场",
"ip": "192.168.10.161",
"location": "出入口"
},
{
"carme_name": "停车场卡口老表右入境摄像头出场",
"ip": "192.168.10.163",
"location": "出入口"
},
{
"carme_name": "槟榔寨站入境摄像头入场",
"ip": "192.168.10.173",
"location": "道路"
},
{
"carme_name": "槟榔寨站入境摄像头出场",
"ip": "192.168.10.174",
"location": "道路"
},
{
"carme_name": "外围冷链停车区入境摄像头出场",
"ip": "192.168.10.158",
"location": "出入口"
},
{
"carme_name": "外围冷链停车区入境摄像头入场",
"ip": "192.168.10.157",
"location": "出入口"
},
{
"carme_name": "清水河隧道出",
"ip": "192.168.10.175",
"location": "道路"
},
{
"carme_name": "清水河隧道入",
"ip": "192.168.10.186",
"location": "道路"
},
{
"carme_name": "商阜路闭环区道路监控-高点",
"ip": "192.168.10.154",
"location": "道路"
},
{
"carme_name": "商阜路闭环区道路监控道路监控高点2",
"ip": "192.168.10.155",
"location": "道路"
},
{
"carme_name": "商阜路闭环区道路监控道路监控-后",
"ip": "192.168.10.152",
"location": "道路"
},
{
"carme_name": "越南城十字路口-东西干道入境摄像头出场",
"ip": "192.168.10.172",
"location": "道路"
},
{
"carme_name": "越南城十字路口-东西干道入境摄像头入场",
"ip": "192.168.10.171",
"location": "道路"
},
{
"carme_name": "停车场卡口能投入境摄像头出场",
"ip": "192.168.10.124",
"location": "出入口"
},
{
"carme_name": "停车场卡口能投入境摄像头入场2",
"ip": "192.168.10.123",
"location": "出入口"
},
{
"carme_name": "停车场卡口能投入境摄像头入场1",
"ip": "192.168.10.122",
"location": "出入口"
},
{
"carme_name": "御峰货场冷链入境摄像头出场出口",
"ip": "192.168.10.145",
"location": "出入口"
},
{
"carme_name": "御峰货场(冷链)-高点",
"ip": "192.168.10.137",
"location": ""
},
{
"carme_name": "御峰货场冷链入境摄像头入场进口",
"ip": "192.168.10.133",
"location": "出入口"
},
{
"carme_name": "御峰货场冷链入境摄像头入场出口",
"ip": "192.168.10.138",
"location": "出入口"
},
{
"carme_name": "御峰货场冷链入境摄像头出场进口",
"ip": "192.168.10.141",
"location": "出入口"
},
{
"carme_name": "御峰货场干货入境摄像头入场",
"ip": "192.168.10.140",
"location": "出入口"
},
{
"carme_name": "御峰货场干货入境摄像头入场2",
"ip": "192.168.10.148",
"location": "出入口"
},
{
"carme_name": "御峰货场干货入境摄像头出场",
"ip": "192.168.10.144",
"location": "出入口"
},
{
"carme_name": "御峰货场(干货)-高点1",
"ip": "192.168.10.142",
"location": ""
},
{
"carme_name": "御峰货场(干货)-高点2",
"ip": "192.168.10.143",
"location": ""
},
{
"carme_name": "御峰货场干货入境摄像头出场2",
"ip": "192.168.10.147",
"location": "出入口"
}],
tensor_fields=["carme_name"]
)
def query_vector_db(query):
return mq.index(INDEX_NAME).search(q=query)
if __name__ == '__main__':
# create_and_set_index()
rt = query_vector_db('南卡口')
# TODO 根据 _score字段 取出相似度最高的结果
if rt:
for ele in rt['hits']:
print(ele)
Loading…
Cancel
Save