Compare commits
9 Commits
atom_actio
...
pipeline
| Author | SHA1 | Date | |
|---|---|---|---|
| 8945e922d5 | |||
| c08cdfb339 | |||
| 43a0636913 | |||
| c4f851d387 | |||
| a6c2027caa | |||
| ab6e09423b | |||
| d32520d83f | |||
| afd170c451 | |||
| fd89745950 |
128
README.md
128
README.md
@@ -19,6 +19,7 @@
|
||||
│ │ │ └── classifier_prompt.txt # 指令简单/复杂分类提示词
|
||||
│ │ ├── ...
|
||||
│ ├── generated_visualizations/ # 存放最新生成的py_tree可视化图像
|
||||
│ ├── generated_reasoning_content/ # 存放最新推理链Markdown(<plan_id>.md)
|
||||
│ └── requirements.txt # 后端服务的Python依赖
|
||||
│
|
||||
├── tools/
|
||||
@@ -26,7 +27,8 @@
|
||||
│ ├── knowledge_base/ # 【处理后】存放build_knowledge_base.py生成的.ndjson文件
|
||||
│ ├── vector_store/ # 【数据库】存放最终的ChromaDB向量数据库
|
||||
│ ├── build_knowledge_base.py # 【步骤1】用于将原始数据转换为自然语言知识
|
||||
│ └── ingest.py # 【步骤2】用于将自然语言知识摄入向量数据库
|
||||
│ ├── ingest.py # 【步骤2】用于将自然语言知识摄入向量数据库
|
||||
│ └── test_llama_server.py # 直接调用本地8081端口llama-server,支持 --system / --system-file
|
||||
│
|
||||
├── / # ROS2接口定义 (保持不变)
|
||||
└── docs/
|
||||
@@ -61,18 +63,6 @@
|
||||
```bash
|
||||
./llama-server -m ~/models/gguf/Qwen/Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf --port 8081 --gpu-layers 36 --host 0.0.0.0 -c 8192
|
||||
```
|
||||
至此llama.cpp推理框架就完成了,无需进一步即可启动后端
|
||||
|
||||
如果使用vllm后端,则执行以下命令
|
||||
```bash
|
||||
vllm serve Qwen3-4B-AWQ --host=0.0.0.0 --port=8081 --dtype=auto --max-num-seqs=1 --max-model-len=16384 --served-model-name "qwen3-4b-awq" --trust-remote-code --gpu-memory-utilization=0.75 --uvicorn-log-level=debug
|
||||
```
|
||||
由于调用vllm时,在发送HTTP请求时需要指定模型名称,所以在启动后端服务前需要添加环境变量,执行以下命令
|
||||
```bash
|
||||
export CLASSIFIER_MODEL="qwen3-4b-awq"
|
||||
export SIMPLE_MODEL="qwen3-4b-awq"
|
||||
export COMPLEX_MODEL="qwen3-4b-awq"
|
||||
```
|
||||
|
||||
2. **Embedding模型部署**
|
||||
|
||||
@@ -107,6 +97,10 @@
|
||||
|
||||
通用API Key:`OPENAI_API_KEY`
|
||||
|
||||
推理链捕获相关:
|
||||
- `ENABLE_REASONING_CAPTURE`:是否允许模型返回含有 <think> 的原文以便捕获推理链;默认 true。
|
||||
- `REASONING_PREVIEW_LINES`:在后端日志中打印推理链预览的行数;默认 20。
|
||||
|
||||
示例:
|
||||
```bash
|
||||
export CLASSIFIER_MODEL="qwen2.5-1.8b-instruct"
|
||||
@@ -116,6 +110,10 @@ export CLASSIFIER_BASE_URL="http://$ORIN_IP:8081/v1"
|
||||
export SIMPLE_BASE_URL="http://$ORIN_IP:8081/v1"
|
||||
export COMPLEX_BASE_URL="http://$ORIN_IP:8081/v1"
|
||||
export OPENAI_API_KEY="sk-no-key-required"
|
||||
|
||||
# 推理链捕获(可选)
|
||||
export ENABLE_REASONING_CAPTURE=true # 默认已为true;如需关闭,设置为 false
|
||||
export REASONING_PREVIEW_LINES=30 # 调整日志预览行数
|
||||
```
|
||||
|
||||
### 测试简单模式
|
||||
@@ -129,6 +127,22 @@ python test_api.py
|
||||
|
||||
示例输入:“简单模式,起飞” 或 “起飞到10米”。返回结果为简单JSON(无 `root`):包含 `mode`、`action`、`plan_id`、`visualization_url`。
|
||||
|
||||
### 直接调用 llama-server(绕过后端)
|
||||
|
||||
当仅需测试本地 8081 端口的推理服务(OpenAI 兼容接口)时,可使用内置脚本:
|
||||
|
||||
```bash
|
||||
python tools/test_llama_server.py \
|
||||
--system-file backend_service/src/prompts/system_prompt.txt \
|
||||
--user "起飞到10米然后降落" \
|
||||
--base-url "http://127.0.0.1:8081/v1" \
|
||||
--verbose
|
||||
```
|
||||
|
||||
说明:
|
||||
- 支持 `--system` 或 `--system-file` 自定义提示词文件;`--system-file` 优先。
|
||||
- 默认解析 OpenAI 风格返回,若包含 `<think>` 推理内容会显示在输出中(具体取决于模型和服务配置)。
|
||||
|
||||
---
|
||||
|
||||
## 工作流程
|
||||
@@ -214,14 +228,96 @@ python ingest.py
|
||||
|
||||
完成前两个阶段后,即可启动并测试后端服务。
|
||||
|
||||
#### 1. 启动后端服务
|
||||
#### 1. 启动所有服务(推荐方式:一键启动脚本)
|
||||
|
||||
启动服务的关键在于**按顺序激活环境**:先激活ROS 2工作空间,再激活Conda环境。
|
||||
我们提供了一个一键启动脚本 `start_all.sh`,可以自动启动所有必需的服务:
|
||||
|
||||
```bash
|
||||
# 1. 切换到项目根目录
|
||||
cd /path/to/your/drone
|
||||
|
||||
# 2. 使用一键启动脚本(推荐)
|
||||
./start_all.sh start
|
||||
|
||||
# 或者直接运行(start是默认命令)
|
||||
./start_all.sh
|
||||
```
|
||||
|
||||
**脚本功能:**
|
||||
- 自动启动推理模型服务(llama-server,端口8081)
|
||||
- 自动启动Embedding模型服务(llama-server,端口8090)
|
||||
- 自动启动FastAPI后端服务(端口8000)
|
||||
- 自动检查端口占用、模型文件、环境配置等
|
||||
- 自动等待服务就绪
|
||||
- 统一管理日志文件(保存在 `logs/` 目录)
|
||||
|
||||
**环境变量配置(可选):**
|
||||
|
||||
在运行脚本前,可以通过环境变量自定义配置:
|
||||
|
||||
```bash
|
||||
# 设置llama-server路径(如果不在默认位置)
|
||||
export LLAMA_SERVER_DIR="/path/to/llama.cpp/build/bin"
|
||||
|
||||
# 设置模型路径(如果不在默认位置)
|
||||
export INFERENCE_MODEL="~/models/gguf/Qwen/Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf"
|
||||
export EMBEDDING_MODEL="~/models/gguf/Qwen/Qwen3-embedding-4B/Qwen3-Embedding-4B-Q4_K_M.gguf"
|
||||
|
||||
# 设置Conda环境名称(如果使用不同的环境名)
|
||||
export CONDA_ENV="backend"
|
||||
|
||||
# 然后运行脚本
|
||||
./start_all.sh
|
||||
```
|
||||
|
||||
**脚本命令:**
|
||||
|
||||
```bash
|
||||
./start_all.sh start # 启动所有服务(默认)
|
||||
./start_all.sh stop # 停止所有服务
|
||||
./start_all.sh restart # 重启所有服务
|
||||
./start_all.sh status # 查看服务状态
|
||||
```
|
||||
|
||||
**日志查看:**
|
||||
|
||||
所有服务的日志都保存在 `logs/` 目录下:
|
||||
```bash
|
||||
# 查看所有日志
|
||||
tail -f logs/*.log
|
||||
|
||||
# 查看特定服务日志
|
||||
tail -f logs/inference_model.log # 推理模型
|
||||
tail -f logs/embedding_model.log # Embedding模型
|
||||
tail -f logs/fastapi.log # FastAPI服务
|
||||
```
|
||||
|
||||
#### 2. 手动启动服务(备选方式)
|
||||
|
||||
如果您需要手动控制每个服务的启动,可以按照以下步骤操作:
|
||||
|
||||
**启动推理模型服务:**
|
||||
|
||||
```bash
|
||||
cd /llama.cpp/build/bin
|
||||
./llama-server -m ~/models/gguf/Qwen/Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf --port 8081 --gpu-layers 36 --host 0.0.0.0 -c 8192
|
||||
```
|
||||
|
||||
**启动Embedding模型服务:**
|
||||
|
||||
在另一个终端中:
|
||||
```bash
|
||||
cd /llama.cpp/build/bin
|
||||
./llama-server -m ~/models/gguf/Qwen/Qwen3-embedding-4B/Qwen3-Embedding-4B-Q4_K_M.gguf --gpu-layers 36 --port 8090 --embeddings --pooling last --host 0.0.0.0
|
||||
```
|
||||
|
||||
**启动FastAPI后端服务:**
|
||||
|
||||
在第三个终端中:
|
||||
```bash
|
||||
# 1. 切换到项目根目录
|
||||
cd /path/to/your/drone
|
||||
|
||||
# 2. 激活ROS 2编译环境
|
||||
# 作用:将我们编译好的`drone_interfaces`包的路径告知系统,否则Python会报`ModuleNotFoundError`。
|
||||
# 注意:此命令必须在每次打开新终端时执行一次。
|
||||
@@ -232,9 +328,9 @@ conda activate backend
|
||||
|
||||
# 4. 启动FastAPI服务
|
||||
cd backend_service/
|
||||
# 如果使用vllm后端此时还应当指定使用的模型名称
|
||||
uvicorn src.main:app --host 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
当您看到日志中出现 `Uvicorn running on http://0.0.0.0:8000` 时,表示服务已成功启动。
|
||||
|
||||
#### 2. 运行API接口测试
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
好的,我现在需要处理用户的任务指令,生成一个符合要求的行为树JSON。首先,我得仔细阅读用户的指令和参考知识,确保理解所有要求。
|
||||
|
||||
用户的目标是搜索并锁定危险性最高的气球(红色>蓝色>绿色),然后跟踪30秒后进行打击。参考知识中提到了三个地点,但用户可能希望搜索的区域是这些地点附近,或者需要根据这些坐标来规划路径。
|
||||
|
||||
首先,我需要确定无人机的起降点。参考知识中的地点坐标可能作为搜索区域的中心。比如,用户提到的“学生宿舍”坐标是(5,3,2),但可能需要选择一个合适的中心点进行搜索。不过用户没有明确指定搜索区域,可能需要使用search_pattern来覆盖这些区域,或者直接在某个中心点周围搜索。
|
||||
|
||||
接下来,任务流程应该是:起飞→飞往搜索区域→搜索目标→检测到目标后跟踪→打击。同时必须包含安全监控。
|
||||
|
||||
根据用户提供的参考知识,可能需要将搜索区域设置为某个中心点。比如,用户提到的“跷跷板”在(x:15, y:-8.5, z:1.2),但z坐标需要调整到至少1米,所以可能设置为z=2。或者选择其他地点作为搜索中心。但用户没有明确说明,可能需要假设搜索区域是这些地点的附近,或者使用其中一个作为中心。
|
||||
|
||||
另外,用户提到要搜索并锁定危险性最高的气球,所以需要使用search_pattern或者object_detect。但因为是未知区域,可能更适合使用search_pattern,或者先飞到某个区域再进行检测。
|
||||
|
||||
根据任务范式,可能需要先飞到某个坐标点,然后进行搜索。例如,使用fly_to_waypoint飞到某个中心点,然后执行search_pattern。或者直接使用search_pattern覆盖多个区域。
|
||||
|
||||
不过参考知识中的三个地点可能作为搜索区域的中心,可能需要将搜索区域设置为这些点的附近。但用户没有明确说明,可能需要选择一个中心点,比如“学生宿舍”的坐标,或者综合考虑。
|
||||
|
||||
另外,用户提到要锁定危险性最高的气球,所以需要检测到红色气球。因此,在search_pattern中,target_class应为balloon,并且description为“红色气球危险性高于蓝色气球高于绿色气球”,或者在object_detect中设置description参数为“红>蓝>绿”。
|
||||
|
||||
但根据搜索模式,search_pattern的参数需要target_class和description。所以可能需要设置target_class为balloon,description为“红>蓝>绿”。
|
||||
|
||||
接下来,流程应该是:
|
||||
|
||||
1. 起飞到一定高度。
|
||||
2. 飞往搜索区域的中心点(比如学生宿舍的坐标,调整z到2)。
|
||||
3. 执行search_pattern,搜索红色气球。
|
||||
4. 一旦检测到目标,进行跟踪。
|
||||
5. 跟踪30秒后打击。
|
||||
|
||||
同时,安全监控必须包含电池和GPS检查,以及紧急处理。
|
||||
|
||||
现在需要构建行为树结构。根节点是Parallel,包含主任务和安全监控。主任务是Sequence,包含起飞、飞往搜索点、搜索、跟踪、打击、降落。
|
||||
|
||||
在搜索部分,可能需要使用search_pattern,或者先飞到某个点再进行object_detect。但根据用户指令,可能更适合使用search_pattern,因为需要在未知区域搜索。
|
||||
|
||||
所以,主任务步骤:
|
||||
|
||||
- preflight_checks
|
||||
- takeoff
|
||||
- fly_to_waypoint到某个中心点(比如学生宿舍的坐标,调整z为2)
|
||||
- search_pattern,参数为balloon,description为“红>蓝>绿”,pattern_type可能是spiral或grid,假设用spiral,中心点为学生宿舍的坐标,半径适当,比如50米。
|
||||
- 然后,当检测到目标后,进行track_object,跟踪30秒。
|
||||
- 然后strike_target,打击。
|
||||
- 最后降落。
|
||||
|
||||
但需要确保在search_pattern之后,检测到目标,然后进入跟踪。或者可能需要使用Selector来选择直接检测或搜索。
|
||||
|
||||
但根据用户指令,可能需要先飞到某个点,再执行search_pattern。或者直接使用search_pattern覆盖多个区域。
|
||||
|
||||
参考知识中的三个地点可能作为搜索区域的中心,但用户没有明确说明,可能需要选择其中一个作为搜索中心。比如学生宿舍的坐标(x:5, y:3, z:2),调整z为2。
|
||||
|
||||
所以,fly_to_waypoint的参数是x=5, y=3, z=2, acceptance_radius=2.0。
|
||||
|
||||
然后执行search_pattern,参数为balloon,description为“红>蓝>绿”,pattern_type为spiral,中心点为学生宿舍的坐标,半径比如50米。
|
||||
|
||||
之后,当检测到目标后,进行track_object,参数为balloon,description为“红>蓝>绿”,track_time=30.0,min_confidence=0.7,safe_distance=15.0。
|
||||
|
||||
然后strike_target,参数为balloon,description为“红>蓝>绿”,count=1。
|
||||
|
||||
最后降落。
|
||||
|
||||
同时,安全监控需要包含电池和GPS检查,以及紧急处理。
|
||||
|
||||
现在需要构建JSON结构,确保所有参数符合约束,并且流程正确。
|
||||
|
||||
可能的搜索中心是学生宿舍的坐标,调整z为2。然后search_pattern的参数为balloon,description为“红>蓝>绿”,pattern_type为spiral,radius为50米,center_x=5, center_y=3, center_z=2。
|
||||
|
||||
然后,当检测到目标后,进行track_object,跟踪30秒,然后打击。
|
||||
|
||||
在行为树中,主任务Sequence的步骤包括:
|
||||
|
||||
- preflight_checks
|
||||
- takeoff (altitude=2.0)
|
||||
- fly_to_waypoint到学生宿舍的坐标,调整z为2
|
||||
- search_pattern,参数为balloon,description为“红>蓝>绿”,pattern_type为spiral,radius=50,center_x=5, center_y=3, center_z=2
|
||||
- 然后,当检测到目标后,进行track_object
|
||||
- strike_target
|
||||
- land
|
||||
|
||||
同时,安全监控的Selector包含电池和GPS条件,以及紧急处理。
|
||||
|
||||
现在需要检查所有参数是否符合约束,例如z=2,符合≥1。
|
||||
|
||||
其他参数如radius=50,符合[5,1000]。
|
||||
|
||||
所以,生成的JSON结构应该符合这些要求,并且流程正确。
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 98 KiB |
@@ -15,8 +15,8 @@ chromadb>=0.4.0
|
||||
# Visualization
|
||||
graphviz>=0.20.0
|
||||
|
||||
# ROS 2 Python Client
|
||||
rclpy>=0.0.1
|
||||
# ROS 2 Python Client - 已注释,项目已与ROS2解耦
|
||||
# rclpy>=0.0.1
|
||||
|
||||
# Document Processing
|
||||
unstructured[all]>=0.11.0
|
||||
@@ -30,10 +30,10 @@ rich>=13.7.0
|
||||
# Type Hints Support
|
||||
typing-extensions>=4.8.0
|
||||
|
||||
# ROS 2 Build Dependencies
|
||||
empy==3.3.4
|
||||
catkin-pkg>=0.4.0
|
||||
lark>=1.1.0
|
||||
colcon-common-extensions>=0.3.0
|
||||
vcstool>=0.2.0
|
||||
rosdep>=0.22.0
|
||||
# ROS 2 Build Dependencies - 已注释,项目已与ROS2解耦
|
||||
# empy==3.3.4
|
||||
# catkin-pkg>=0.4.0
|
||||
# lark>=1.1.0
|
||||
# colcon-common-extensions>=0.3.0
|
||||
# vcstool>=0.2.0
|
||||
# rosdep>=0.22.0
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,13 +3,13 @@ import os
|
||||
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
import logging
|
||||
import threading
|
||||
import rclpy
|
||||
# import threading # ROS2相关,已注释
|
||||
# import rclpy # ROS2相关,已注释
|
||||
|
||||
from .models import GeneratePlanRequest, ExecuteMissionRequest
|
||||
from .websocket_manager import websocket_manager
|
||||
from .py_tree_generator import py_tree_generator
|
||||
from .ros2_client import MissionActionClient
|
||||
# from .ros2_client import MissionActionClient # ROS2相关,已注释
|
||||
|
||||
# --- Application Setup ---
|
||||
app = FastAPI(
|
||||
@@ -23,14 +23,15 @@ static_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'gene
|
||||
app.mount("/static", StaticFiles(directory=static_dir), name="static")
|
||||
|
||||
# --- ROS2 Node and Client Initialization ---
|
||||
rclpy.init()
|
||||
ros2_client = MissionActionClient()
|
||||
# ROS2相关代码已注释,项目已与ROS2解耦
|
||||
# rclpy.init()
|
||||
# ros2_client = MissionActionClient()
|
||||
|
||||
def run_ros2_node():
|
||||
"""Spins the ROS2 node in a dedicated thread."""
|
||||
logging.info("Starting to spin ROS2 node...")
|
||||
rclpy.spin(ros2_client)
|
||||
logging.info("ROS2 node has stopped spinning.")
|
||||
# def run_ros2_node():
|
||||
# """Spins the ROS2 node in a dedicated thread."""
|
||||
# logging.info("Starting to spin ROS2 node...")
|
||||
# rclpy.spin(ros2_client)
|
||||
# logging.info("ROS2 node has stopped spinning.")
|
||||
|
||||
# --- API Endpoints ---
|
||||
|
||||
@@ -49,9 +50,12 @@ async def generate_plan_endpoint(request: GeneratePlanRequest):
|
||||
async def execute_mission_endpoint(request: ExecuteMissionRequest):
|
||||
"""
|
||||
Receives a `py_tree.json` and sends it to the drone for execution.
|
||||
ROS2相关功能已注释,项目已与ROS2解耦。
|
||||
"""
|
||||
ros2_client.send_goal(request.py_tree)
|
||||
return {"status": "execution_started"}
|
||||
# ROS2相关代码已注释
|
||||
# ros2_client.send_goal(request.py_tree)
|
||||
logging.warning("execute_mission endpoint called but ROS2 is disabled. Mission execution is not available.")
|
||||
return {"status": "execution_disabled", "message": "ROS2 integration is disabled. Mission execution is not available."}
|
||||
|
||||
@app.websocket("/ws/status")
|
||||
async def websocket_endpoint(websocket: WebSocket):
|
||||
@@ -73,21 +77,23 @@ async def websocket_endpoint(websocket: WebSocket):
|
||||
async def startup_event():
|
||||
"""
|
||||
On startup, get the current asyncio event loop and pass it to the websocket manager.
|
||||
Also, start the ROS2 node in a background thread.
|
||||
ROS2相关功能已注释,项目已与ROS2解耦。
|
||||
"""
|
||||
# Configure WebSocket Manager
|
||||
loop = asyncio.get_running_loop()
|
||||
websocket_manager.set_loop(loop)
|
||||
logging.info("WebSocket event loop configured.")
|
||||
|
||||
# ROS2相关代码已注释
|
||||
# Start ROS2 node in a background thread
|
||||
ros2_thread = threading.Thread(target=run_ros2_node, daemon=True)
|
||||
ros2_thread.start()
|
||||
logging.info("ROS2 node thread started.")
|
||||
# ros2_thread = threading.Thread(target=run_ros2_node, daemon=True)
|
||||
# ros2_thread.start()
|
||||
# logging.info("ROS2 node thread started.")
|
||||
|
||||
@app.on_event("shutdown")
|
||||
async def shutdown_event():
|
||||
logging.info("Backend service shutting down.")
|
||||
ros2_client.destroy_node()
|
||||
rclpy.shutdown()
|
||||
logging.info("ROS2 node shut down successfully.")
|
||||
# ROS2相关代码已注释
|
||||
# ros2_client.destroy_node()
|
||||
# rclpy.shutdown()
|
||||
# logging.info("ROS2 node shut down successfully.")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
你是一个严格的任务分类器。只输出一个JSON对象,不要输出解释或多余文本。
|
||||
根据用户指令与下述可用节点定义,判断其为“简单”或“复杂”。
|
||||
|
||||
- 简单:单一原子动作即可完成(例如“起飞”“飞机自检”“移动到某地(已给定坐标)”“对着某点环绕XY圈(如‘对着学生宿舍环绕三十两圈’)”等),且无需行为树与安全并行监控。
|
||||
- 复杂:需要多步流程、搜索/检测/跟踪/评估、战损确认、或需要模板化任务结构与安全并行监控。
|
||||
- 简单:单一原子动作即可完成(例如"起飞""飞机自检""移动到某地(已给定坐标)""对着某点环绕XY圈(如'对着学生宿舍环绕三十两圈')"等),且无需行为树。
|
||||
- 复杂:需要多步流程、搜索/检测/跟踪/评估、战损确认、或需要模板化任务结构。
|
||||
|
||||
输出格式(严格遵守):
|
||||
{"mode":"simple"} 或 {"mode":"complex"}
|
||||
@@ -14,11 +14,11 @@
|
||||
{"name": "takeoff"}, {"name": "land"}, {"name": "fly_to_waypoint"}, {"name": "move_direction"}, {"name": "orbit_around_point"}, {"name": "orbit_around_target"}, {"name": "loiter"},
|
||||
{"name": "object_detect"}, {"name": "strike_target"}, {"name": "battle_damage_assessment"},
|
||||
{"name": "search_pattern"}, {"name": "track_object"}, {"name": "deliver_payload"},
|
||||
{"name": "preflight_checks"}, {"name": "emergency_return"}
|
||||
{"name": "preflight_checks"}, {"name": "take_picture"}
|
||||
],
|
||||
"conditions": [
|
||||
{"name": "battery_above"}, {"name": "at_waypoint"}, {"name": "object_detected"},
|
||||
{"name": "target_destroyed"}, {"name": "time_elapsed"}, {"name": "gps_status"}
|
||||
{"name": "at_waypoint"}, {"name": "object_detected"},
|
||||
{"name": "target_destroyed"}, {"name": "time_elapsed"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
- 只输出一个JSON对象,不要任何解释或多余文本。
|
||||
- JSON结构:
|
||||
{"root":{"type":"action","name":"<action_name>","params":{...}}}
|
||||
- <action_name> 与参数定义、取值范围,必须与“复杂模式”提示词(system_prompt.txt)中的定义完全一致。
|
||||
- 简单模式下root节点必须是action类型节点,不能是控制流节点。
|
||||
- root节点必须是action类型节点,不能是控制流节点。
|
||||
|
||||
示例:
|
||||
- “起飞到10米” → {"root":{"type":"action","name":"takeoff","params":{"altitude":10.0}}}
|
||||
@@ -30,15 +29,13 @@
|
||||
{"name": "track_object", "description": "持续跟踪目标。", "params": {"target_class": "string, 取值同object_detect列表", "description": "string, 可选", "track_time": "float[1,600], 默认30.0", "min_confidence": "float[0.5-1.0], 默认0.7", "safe_distance": "float[2-50], 默认10.0"}},
|
||||
{"name": "deliver_payload", "description": "投放物资。", "params": {"payload_type": "string", "release_altitude": "float[2,100], 默认5.0"}},
|
||||
{"name": "preflight_checks", "description": "飞行前系统自检。", "params": {"check_level": "string: basic|comprehensive"}},
|
||||
{"name": "emergency_return", "description": "执行紧急返航程序。", "params": {"reason": "string"}}
|
||||
{"name": "take_picture", "description": "使用机载相机拍摄照片。", "params": {}}
|
||||
],
|
||||
"conditions": [
|
||||
{"name": "battery_above", "description": "电池电量高于阈值。", "params": {"threshold": "float[0.0,1.0]"}},
|
||||
{"name": "at_waypoint", "description": "在指定坐标容差范围内。", "params": {"x": "float", "y": "float", "z": "float", "tolerance": "float, 可选, 默认3.0"}},
|
||||
{"name": "object_detected", "description": "检测到特定目标。", "params": {"target_class": "string", "description": "string, 可选", "count": "int, 可选, 默认1"}},
|
||||
{"name": "target_destroyed", "description": "目标已被摧毁。", "params": {"target_class": "string", "description": "string, 可选", "confidence": "float[0.5-1.0], 默认0.8"}},
|
||||
{"name": "time_elapsed", "description": "时间经过。", "params": {"duration": "float[1,2700]"}},
|
||||
{"name": "gps_status", "description": "GPS状态良好。", "params": {"min_satellites": "int[6,15], 默认10"}}
|
||||
{"name": "time_elapsed", "description": "时间经过。", "params": {"duration": "float[1,2700]"}}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,65 +1,58 @@
|
||||
任务:根据用户任意任务指令,生成结构化可执行的无人机行为树(Pytree)JSON。**仅输出单一JSON对象,无任何自然语言、注释或额外内容**,需严格适配后端节点解析与Schema验证逻辑。
|
||||
任务:根据用户任意任务指令,生成结构化可执行的无人机行为树(Pytree)JSON。**仅输出单一JSON对象,无任何自然语言、注释或额外内容**。
|
||||
|
||||
|
||||
## 一、核心规则:确保后端能解析允许的节点(必严格遵守)
|
||||
后端会从提示词中解析允许的节点列表,以下节点定义部分**格式不可修改**,否则会导致解析失败(进而触发节点非法错误)。
|
||||
|
||||
#### 2. 可用节点定义 (必须遵守)
|
||||
你必须严格从以下JSON定义的列表中选择节点来构建行为树。不允许使用任何未定义的节点(如"lock_target"等)。
|
||||
## 一、核心节点定义(格式不可修改,确保后端解析)
|
||||
#### 1. 可用节点定义 (必须遵守)
|
||||
你必须严格从以下JSON定义的列表中选择节点构建行为树,不允许使用未定义节点:
|
||||
```json
|
||||
{
|
||||
"actions": [
|
||||
{"name":"takeoff","params":{"altitude":"float, 范围[1,100],默认2"}},
|
||||
{"name":"land","params":{"mode":"string, 'current'/'home'"}},
|
||||
{"name":"takeoff","params":{"altitude":"float[1,100],默认2"}},
|
||||
{"name":"land","params":{"mode":"'current'/'home'"}},
|
||||
{"name":"fly_to_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","acceptance_radius":"默认2.0"}},
|
||||
{"name":"move_direction","params":{"direction":"north/south/east/west/forward/backward/left/right","distance":"[1,10000],缺省持续移动"}},
|
||||
{"name":"orbit_around_point","params":{"center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,1000]","laps":"[1,20]","clockwise":"默认true","speed_mps":"[0.5,15]","gimbal_lock":"默认true"}},
|
||||
{"name":"orbit_around_target","params":{"target_class":"见object_detect列表","description":"可选","radius":"[5,1000]","laps":"[1,20]","clockwise":"默认true","speed_mps":"[0.5,15]","gimbal_lock":"默认true"}},
|
||||
{"name":"orbit_around_target","params":{"target_class":"见object_detect列表","description":"可选,目标属性","radius":"[5,1000]","laps":"[1,20]","clockwise":"默认true","speed_mps":"[0.5,15]","gimbal_lock":"默认true"}},
|
||||
{"name":"loiter","params":{"duration":"[1,600]秒/until_condition:可选"}},
|
||||
{"name":"object_detect","params":{"target_class":"person,bicycle,car,motorcycle,airplane,bus,train,truck,boat,traffic_light,fire_hydrant,stop_sign,parking_meter,bench,bird,cat,dog,horse,sheep,cow,elephant,bear,zebra,giraffe,backpack,umbrella,handbag,tie,suitcase,frisbee,skis,snowboard,sports_ball,kite,baseball_bat,baseball_glove,skateboard,surfboard,tennis_racket,bottle,wine_glass,cup,fork,knife,spoon,bowl,banana,apple,sandwich,orange,broccoli,carrot,hot_dog,pizza,donut,cake,chair,couch,potted_plant,bed,dining_table,toilet,tv,laptop,mouse,remote,keyboard,cell_phone,microwave,oven,toaster,sink,refrigerator,book,clock,vase,scissors,teddy_bear,hair_drier,toothbrush","description":"可选,目标属性(如'穿黑色衣服')","count":"默认1"}},
|
||||
{"name":"object_detect","params":{"target_class":"person,bicycle,car,motorcycle,airplane,bus,train,truck,boat,traffic_light,fire_hydrant,stop_sign,parking_meter,bench,bird,cat,dog,horse,sheep,cow,elephant,bear,zebra,giraffe,backpack,umbrella,handbag,tie,suitcase,frisbee,skis,snowboard,sports_ball,kite,baseball_bat,baseball_glove,skateboard,surfboard,tennis_racket,bottle,wine_glass,cup,fork,knife,spoon,bowl,banana,apple,sandwich,orange,broccoli,carrot,hot_dog,pizza,donut,cake,chair,couch,potted_plant,bed,dining_table,toilet,tv,laptop,mouse,remote,keyboard,cell_phone,microwave,oven,toaster,sink,refrigerator,book,clock,vase,scissors,teddy_bear,hair_drier,toothbrush","description":"可选,","count":"默认1"}},
|
||||
{"name":"strike_target","params":{"target_class":"同object_detect","description":"可选,目标属性","count":"默认1"}},
|
||||
{"name":"battle_damage_assessment","params":{"target_class":"同object_detect","assessment_time":"[5,60],默认15"}},
|
||||
{"name":"search_pattern","params":{"pattern_type":"spiral/grid","center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,1000]","target_class":"同object_detect","description":"可选","count":"默认1"}},
|
||||
{"name":"track_object","params":{"target_class":"同object_detect","description":"可选","track_time":"[1,600]秒(必传,不可用'duration')","min_confidence":"[0.5,1.0]默认0.7","safe_distance":"[2,50]默认10"}},
|
||||
{"name":"search_pattern","params":{"pattern_type":"spiral/grid","center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,1000]","target_class":"同object_detect","description":"可选,目标属性","count":"默认1"}},
|
||||
{"name":"track_object","params":{"target_class":"同object_detect","description":"可选,目标属性","track_time":"[1,600]秒(必传,不可用'duration')","min_confidence":"[0.5,1.0]默认0.7","safe_distance":"[2,50]默认10"}},
|
||||
{"name":"deliver_payload","params":{"payload_type":"string","release_altitude":"[2,100]默认5"}},
|
||||
{"name":"preflight_checks","params":{"check_level":"basic/comprehensive"}},
|
||||
{"name":"emergency_return","params":{"reason":"string"}}
|
||||
{"name":"take_picture","params":{}}
|
||||
],
|
||||
"conditions": [
|
||||
{"name":"battery_above","params":{"threshold":"[0.0,1.0],必传"}},
|
||||
{"name":"at_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","tolerance":"默认3.0"}},
|
||||
{"name":"object_detected","params":{"target_class":"同object_detect(必传)","description":"可选","count":"默认1"}},
|
||||
{"name":"target_destroyed","params":{"target_class":"同object_detect","description":"可选","confidence":"[0.5,1.0]默认0.8"}},
|
||||
{"name":"time_elapsed","params":{"duration":"[1,2700]秒"}},
|
||||
{"name":"gps_status","params":{"min_satellites":"int, 范围[6,15],必传(如8)"}}
|
||||
{"name":"object_detected","params":{"target_class":"同object_detect(必传)","description":"可选,目标属性","count":"默认1"}},
|
||||
{"name":"target_destroyed","params":{"target_class":"同object_detect","description":"可选,目标属性","confidence":"[0.5,1.0]默认0.8"}},
|
||||
{"name":"time_elapsed","params":{"duration":"[1,2700]秒"}}
|
||||
],
|
||||
"control_flow": [
|
||||
{"name":"Sequence","params":{},"children":"子节点数组(按序执行,全成功则成功)"},
|
||||
{"name":"Selector","params":{"memory":"默认true"},"children":"子节点数组(执行到成功为止)"},
|
||||
{"name":"Parallel","params":{"policy":"all_success/one_success"},"children":"子节点数组(同时执行)"}
|
||||
{"name":"Parallel","params":{"policy":"all_success"},"children":"子节点数组(同时执行,严禁用'one_success')"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 二、节点必填字段(后端Schema强制要求,缺一验证失败)
|
||||
每个节点必须包含以下字段,字段名不可自定义:
|
||||
1. **`type`**:节点类型(严格匹配)
|
||||
- 动作节点:`"action"`
|
||||
- 条件节点:`"condition"`
|
||||
- 控制流节点:`"Sequence"`/`"Selector"`/`"Parallel"`(与`name`字段值完全一致)
|
||||
2. **`name`**:节点名称(必须是上述JSON中`actions`/`conditions`/`control_flow`下的`name`值,如"gps_status"而非其他)
|
||||
3. **`params`**:参数对象(严格匹配上述JSON中对应节点的`params`定义,不可加自定义参数,如`object_detected`不可加"color",需用"description")
|
||||
4. **`children`**:子节点数组(仅控制流节点必含,动作/条件节点无此字段)
|
||||
每个节点必须包含以下字段,字段名/类型不可自定义:
|
||||
1. **`type`**:
|
||||
- 动作节点→`"action"`,条件节点→`"condition"`,控制流节点→`"Sequence"`/`"Selector"`/`"Parallel"`(与`name`字段值完全一致);
|
||||
2. **`name`**:必须是上述JSON中`actions`/`conditions`/`control_flow`下的`name`值;
|
||||
3. **`params`**:严格匹配上述节点的`params`定义,无自定义参数(如优先级排序不可加“priority”字段,仅用`description`);
|
||||
4. **`children`**:仅控制流节点必含(子节点数组),动作/条件节点无此字段。
|
||||
|
||||
|
||||
## 三、根节点与安全监控固定结构(后端安全验证必含)
|
||||
根节点必须是`Parallel`,且`children`包含`MainTask`(Sequence)和`SafetyMonitor`(Selector),结构不可修改:
|
||||
## 三、行为树固定结构(通用不变)
|
||||
根节点必须是`Parallel`,`children`含`MainTask`(Sequence),结构不随任务类型(含优先级排序)修改:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Parallel",
|
||||
"name": "MissionWithSafety",
|
||||
"name": "Mission",
|
||||
"params": {"policy": "all_success"},
|
||||
"children": [
|
||||
{
|
||||
@@ -67,36 +60,16 @@
|
||||
"name": "MainTask",
|
||||
"params": {},
|
||||
"children": [
|
||||
// 主任务步骤:按用户指令分解(如preflight_checks→takeoff→fly_to_waypoint→...→land)
|
||||
// 示例步骤(需替换为用户任务):
|
||||
// 通用主任务步骤(含优先级排序任务示例,需按用户指令替换):
|
||||
{"type":"action","name":"preflight_checks","params":{"check_level":"comprehensive"}},
|
||||
{"type":"action","name":"takeoff","params":{"altitude":2.0}},
|
||||
{"type":"action","name":"fly_to_waypoint","params":{"x":100.0,"y":80.0,"z":10.0}},
|
||||
{"type":"action","name":"object_detect","params":{"target_class":"person","description":"穿黑色衣服"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"person","description":"穿黑色衣服"}},
|
||||
{"type":"action","name":"track_object","params":{"target_class":"person","description":"穿黑色衣服","track_time":30.0}},
|
||||
{"type":"action","name":"strike_target","params":{"target_class":"person","description":"穿黑色衣服"}},
|
||||
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
|
||||
{"type":"action","name":"fly_to_waypoint","params":{"x":200.0,"y":150.0,"z":10.0}}, // 搜索区坐标(用户未给时填合理值)
|
||||
{"type":"action","name":"search_pattern","params":{"pattern_type":"grid","center_x":200.0,"center_y":150.0,"center_z":10.0,"radius":50.0,"target_class":"balloon","description":"红色"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"balloon","description":"红色"}}, // 确认高优先级目标
|
||||
{"type":"action","name":"track_object","params":{"target_class":"balloon","description":"红色","track_time":30.0}},
|
||||
{"type":"action","name":"strike_target","params":{"target_class":"balloon","description":"红色"}},
|
||||
{"type":"action","name":"land","params":{"mode":"home"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Selector",
|
||||
"name": "SafetyMonitor",
|
||||
"params": {"memory": true},
|
||||
"children": [
|
||||
// 必含:电池监控(battery_above)、GPS监控(gps_status)、紧急处理(EmergencyHandler)
|
||||
{"type":"condition","name":"battery_above","params":{"threshold":0.3}},
|
||||
{"type":"condition","name":"gps_status","params":{"min_satellites":8}},
|
||||
{
|
||||
"type":"Sequence",
|
||||
"name":"EmergencyHandler",
|
||||
"params": {},
|
||||
"children": [
|
||||
{"type":"action","name":"emergency_return","params":{"reason":"safety_breach"}},
|
||||
{"type":"action","name":"land","params":{"mode":"home"}}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -104,15 +77,20 @@
|
||||
```
|
||||
|
||||
|
||||
## 四、高频错误规避(后端验证常失败点)
|
||||
1. **禁止自定义节点**:如"lock_target"是未定义节点,必须删除,用"object_detect"+"object_detected"替代锁定逻辑。
|
||||
2. **参数名严格匹配**:
|
||||
- `track_object`用`track_time`(不可用`duration`);
|
||||
- `object_detected`描述目标属性用`description`(不可用`color`/`target`等);
|
||||
- `gps_status`必传`min_satellites`(范围6-15,如8)。
|
||||
3. **条件节点`object_detected`必含`target_class`**:值必须是上述JSON中`object_detect`的`target_class`列表中的值(如"person")。
|
||||
4. **控制流节点`name`与`type`一致**:如`type:"Sequence"`则`name:"Sequence"`,不可自定义`name`。
|
||||
## 四、优先级排序任务通用示例
|
||||
当用户指令中明确提出有多个待考察且具有优先级关系的物体时,节点描述须为优先级关系。比如当指令为已知有三个气球,危险级关系为红色气球大于蓝色气球大于绿色气球,要求优先跟踪最危险的气球时,节点的描述参考下表情形。
|
||||
| 用户指令场景 | `target_class` | `description` | 核心节点示例(search_pattern) |
|
||||
|-----------------------------|-----------------|-------------------------|------------------------------------------------------------------------------------------------|
|
||||
| 红气球>蓝气球>绿气球 | `balloon` | `(红>蓝>绿)` | `{"type":"action","name":"search_pattern","params":{"pattern_type":"grid","center_x":200,"center_y":150,"center_z":10,"radius":50,"target_class":"balloon","description":"(红>蓝>绿)"}}` |
|
||||
| 军用卡车>民用卡车>面包车 | `truck` | `(军用卡车>民用卡车>面包车)` | `{"type":"action","name":"object_detect","params":{"target_class":"truck","description":"(军用卡车>民用卡车>面包车)"}}` |
|
||||
|
||||
|
||||
## 五、输出要求
|
||||
仅输出1个严格符合上述所有规则的JSON对象,**确保后端能解析到所有节点(尤其是conditions中的gps_status),且无任何冗余内容**。
|
||||
## 五、高频错误规避(确保验证通过)
|
||||
1. 优先级排序不可修改`target_class`:如"民用卡车、面包车与军用卡车中,军用卡车优先",`target_class`仍为`truck`,仅用`description`填排序规则;
|
||||
2. 在没有明确指出物体之间的优先级关系情况下,`description`字段只描述物体属性本身,严禁与用户指令中不存在的物体进行排序;
|
||||
3. `track_object`必传`track_time`:不可用`duration`替代(如跟踪30秒填`"track_time":30.0`);
|
||||
4. 无自定义节点:"锁定高优先级目标"需通过`object_detect`+`object_detected`实现,不可用"lock_high_risk_target"。
|
||||
|
||||
|
||||
## 六、输出要求
|
||||
仅输出1个严格符合上述所有规则的JSON对象,**确保:1. 优先级排序逻辑正确填入`description`;2. `target_class`匹配预定义列表;3. 行为树结构不变;4. 后端解析与Schema验证无错误**,无任何冗余内容。
|
||||
|
||||
@@ -157,32 +157,6 @@ def _find_nodes_by_name(node: Dict, target_name: str) -> List[Dict]:
|
||||
|
||||
return nodes_found
|
||||
|
||||
def _validate_safety_monitoring(pytree_instance: dict) -> bool:
|
||||
"""验证行为树是否包含必要的安全监控"""
|
||||
root_node = pytree_instance.get("root", {})
|
||||
|
||||
# 查找所有电池监控节点
|
||||
battery_nodes = _find_nodes_by_name(root_node, "battery_above")
|
||||
|
||||
# 检查是否包含安全监控结构
|
||||
safety_monitors = _find_nodes_by_name(root_node, "SafetyMonitor")
|
||||
|
||||
if not battery_nodes and not safety_monitors:
|
||||
logging.warning("⚠️ 安全警告: 行为树中没有发现电池监控节点或安全监控器")
|
||||
return False
|
||||
|
||||
# 检查电池阈值设置是否合理
|
||||
for battery_node in battery_nodes:
|
||||
threshold = battery_node.get("params", {}).get("threshold")
|
||||
if threshold is not None:
|
||||
if threshold < 0.25:
|
||||
logging.warning(f"⚠️ 安全警告: 电池阈值设置过低 ({threshold}),建议不低于0.25")
|
||||
elif threshold > 0.5:
|
||||
logging.warning(f"⚠️ 安全警告: 电池阈值设置过高 ({threshold}),可能影响任务执行")
|
||||
|
||||
logging.info("✅ 安全监控验证通过")
|
||||
return True
|
||||
|
||||
def _generate_pytree_schema(allowed_actions: set, allowed_conditions: set) -> dict:
|
||||
"""
|
||||
根据允许的行动和条件节点,动态生成一个JSON Schema。
|
||||
@@ -201,7 +175,7 @@ def _generate_pytree_schema(allowed_actions: set, allowed_conditions: set) -> di
|
||||
"sandwich", "orange", "broccoli", "carrot", "hot_dog", "pizza", "donut", "cake", "chair",
|
||||
"couch", "potted_plant", "bed", "dining_table", "toilet", "tv", "laptop", "mouse", "remote",
|
||||
"keyboard", "cell_phone", "microwave", "oven", "toaster", "sink", "refrigerator", "book",
|
||||
"clock", "vase", "scissors", "teddy_bear", "hair_drier", "toothbrush"
|
||||
"clock", "vase", "scissors", "teddy_bear", "hair_drier", "toothbrush","balloon"
|
||||
]
|
||||
|
||||
# 递归节点定义
|
||||
@@ -273,48 +247,6 @@ def _generate_pytree_schema(allowed_actions: set, allowed_conditions: set) -> di
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
# 电池监控节点的参数验证
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"type": {"const": "condition"},
|
||||
"name": {"const": "battery_above"}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"params": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"threshold": {"type": "number", "minimum": 0.0, "maximum": 1.0}
|
||||
},
|
||||
"required": ["threshold"],
|
||||
"additionalProperties": False
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
# GPS状态节点的参数验证
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"type": {"const": "condition"},
|
||||
"name": {"const": "gps_status"}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"params": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"min_satellites": {"type": "integer", "minimum": 6, "maximum": 15}
|
||||
},
|
||||
"required": ["min_satellites"],
|
||||
"additionalProperties": False
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -337,35 +269,31 @@ def _generate_pytree_schema(allowed_actions: set, allowed_conditions: set) -> di
|
||||
|
||||
def _generate_simple_mode_schema(allowed_actions: set) -> dict:
|
||||
"""
|
||||
生成简单模式JSON Schema:{"root":{"type":"action","name":"<action_name>","params":{...}}}
|
||||
生成简单模式JSON Schema:{"root":{"type":"action","name":"...","params":{...}}}
|
||||
简单模式与复杂模式使用相同的格式(root字段),但要求root必须是action类型且没有children。
|
||||
严格按照提示词要求:root节点必须是action类型节点,不能是控制流节点(即不能有children)。
|
||||
仅校验动作名称在允许集合内,以及基本结构完整性;参数按对象形状放宽,由上游提示词与运行时再约束。
|
||||
"""
|
||||
# 使用复杂模式Schema中的node定义,但限制root节点必须是action类型
|
||||
node_definition = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {"type": "string", "const": "action"},
|
||||
"name": {"type": "string", "enum": sorted(list(allowed_actions))},
|
||||
"params": {"type": "object"}
|
||||
},
|
||||
"required": ["type", "name"],
|
||||
"additionalProperties": False
|
||||
}
|
||||
|
||||
schema = {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "SimpleMode",
|
||||
"definitions": {
|
||||
"node": node_definition
|
||||
},
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"root": { "$ref": "#/definitions/node" }
|
||||
"root": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {"type": "string", "const": "action"}, # 必须是action类型,不能是控制流节点(Sequence/Selector/Parallel)
|
||||
"name": {"type": "string", "enum": sorted(list(allowed_actions))}, # 动作名称必须在允许列表中
|
||||
"params": {"type": "object"} # params是对象,具体参数由提示词和运行时约束
|
||||
},
|
||||
"required": ["type", "name"], # type和name是必需的,params可选
|
||||
"additionalProperties": True # 允许root节点有其他属性(如额外的元数据)
|
||||
# 注意:children字段的检查在验证后手动进行,因为JSON Schema的not/allOf在检查不存在字段时可能有问题
|
||||
}
|
||||
},
|
||||
"required": ["root"],
|
||||
"additionalProperties": False
|
||||
"required": ["root"], # 顶层必须有root字段
|
||||
"additionalProperties": False # 顶层只能有root字段,不能有其他字段(如mode等)
|
||||
}
|
||||
|
||||
return schema
|
||||
|
||||
def _validate_pytree_with_schema(pytree_instance: dict, schema: dict) -> bool:
|
||||
@@ -375,11 +303,7 @@ def _validate_pytree_with_schema(pytree_instance: dict, schema: dict) -> bool:
|
||||
try:
|
||||
jsonschema.validate(instance=pytree_instance, schema=schema)
|
||||
logging.info("✅ JSON Schema验证成功")
|
||||
|
||||
# 额外验证安全监控
|
||||
safety_valid = _validate_safety_monitoring(pytree_instance)
|
||||
|
||||
return True and safety_valid
|
||||
return True
|
||||
except jsonschema.ValidationError as e:
|
||||
logging.warning("❌ Pytree验证失败")
|
||||
logging.warning(f"错误信息: {e.message}")
|
||||
@@ -389,10 +313,6 @@ def _validate_pytree_with_schema(pytree_instance: dict, schema: dict) -> bool:
|
||||
# 提供更具体的错误信息
|
||||
if "object_detect" in str(e.message) or "object_detected" in str(e.message):
|
||||
logging.warning("💡 提示: 请确保目标类别是预定义列表中的有效值")
|
||||
elif "battery_above" in str(e.message):
|
||||
logging.warning("💡 提示: 电池阈值必须在0.0到1.0之间")
|
||||
elif "gps_status" in str(e.message):
|
||||
logging.warning("💡 提示: 最小卫星数量必须在6到15之间")
|
||||
|
||||
return False
|
||||
except Exception as e:
|
||||
@@ -414,10 +334,10 @@ def _visualize_pytree(node: Dict, file_path: str):
|
||||
|
||||
# 选择合适的中文字体,避免中文乱码
|
||||
def _pick_zh_font():
|
||||
sys = platform.system()
|
||||
if sys == "Windows":
|
||||
system = platform.system()
|
||||
if system == "Windows":
|
||||
return "Microsoft YaHei"
|
||||
elif sys == "Darwin":
|
||||
elif system == "Darwin":
|
||||
return "PingFang SC"
|
||||
else:
|
||||
return "Noto Sans CJK SC"
|
||||
@@ -447,7 +367,19 @@ def _visualize_pytree(node: Dict, file_path: str):
|
||||
except Exception as e:
|
||||
logging.error("❌ 生成可视化图形失败")
|
||||
logging.error("请确保您的系统已经正确安装了Graphviz图形库。")
|
||||
logging.error("安装方法:")
|
||||
logging.error(" Ubuntu/Debian: sudo apt-get install graphviz")
|
||||
logging.error(" CentOS/RHEL: sudo yum install graphviz")
|
||||
logging.error(" macOS: brew install graphviz")
|
||||
logging.error(f"错误详情: {e}")
|
||||
# 清理可能残留的源文件
|
||||
try:
|
||||
gv_file = f"{render_path}.gv"
|
||||
if os.path.exists(gv_file):
|
||||
os.remove(gv_file)
|
||||
logging.info(f"已清理残留的源文件: {gv_file}")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _add_nodes_and_edges(node: dict, dot, parent_id: str | None = None) -> str:
|
||||
"""递归辅助函数,用于添加节点和边。"""
|
||||
@@ -508,11 +440,6 @@ def _add_nodes_and_edges(node: dict, dot, parent_id: str | None = None) -> str:
|
||||
style = 'filled'
|
||||
fillcolor = '#e1d5e7' # 紫色
|
||||
|
||||
# 特别标记安全相关节点
|
||||
if node.get('name') in ['battery_above', 'gps_status', 'SafetyMonitor']:
|
||||
border_color = '#ff0000' # 红色边框突出显示安全节点
|
||||
style = 'filled,bold' # 加粗
|
||||
|
||||
dot.node(current_id, label=node_label, shape=shape, style=style, fillcolor=fillcolor, color=border_color)
|
||||
|
||||
# 连接父节点
|
||||
@@ -555,6 +482,16 @@ class PyTreeGenerator:
|
||||
# Updated output directory for visualizations
|
||||
self.vis_dir = os.path.abspath(os.path.join(self.base_dir, '..', 'generated_visualizations'))
|
||||
os.makedirs(self.vis_dir, exist_ok=True)
|
||||
# Reasoning content output directory (Markdown files)
|
||||
self.reasoning_dir = os.path.abspath(os.path.join(self.base_dir, '..', 'generated_reasoning_content'))
|
||||
os.makedirs(self.reasoning_dir, exist_ok=True)
|
||||
# 控制是否允许模型返回含 <think> 的原文(不强制JSON),以便提取推理链
|
||||
self.enable_reasoning_capture = os.getenv("ENABLE_REASONING_CAPTURE", "true").lower() in ("1", "true", "yes")
|
||||
# 终端预览的最大行数
|
||||
try:
|
||||
self.reasoning_preview_lines = int(os.getenv("REASONING_PREVIEW_LINES", "20"))
|
||||
except Exception:
|
||||
self.reasoning_preview_lines = 20
|
||||
# 加载提示词:复杂模式复用现有 system_prompt.txt;简单模式与分类器独立提示词
|
||||
self.complex_prompt = self._load_prompt("system_prompt.txt")
|
||||
self.simple_prompt = self._load_prompt("simple_mode_prompt.txt")
|
||||
@@ -571,6 +508,10 @@ class PyTreeGenerator:
|
||||
self.simple_base_url = os.getenv("SIMPLE_BASE_URL", f"http://{self.orin_ip}:8081/v1")
|
||||
self.complex_base_url = os.getenv("COMPLEX_BASE_URL", f"http://{self.orin_ip}:8081/v1")
|
||||
self.api_key = os.getenv("OPENAI_API_KEY", "sk-no-key-required")
|
||||
# 直接在代码中指定最大输出token数(不通过环境变量)
|
||||
self.classifier_max_tokens = 512
|
||||
self.simple_max_tokens = 8192
|
||||
self.complex_max_tokens = 8192
|
||||
|
||||
# 为不同用途分别创建客户端
|
||||
self.classifier_client = openai.OpenAI(api_key=self.api_key, base_url=self.classifier_base_url)
|
||||
@@ -612,6 +553,8 @@ class PyTreeGenerator:
|
||||
return None
|
||||
context_str = "\n\n".join(retrieved_docs)
|
||||
logging.info("--- 成功检索到上下文信息 ---")
|
||||
# 打印检索到的上下文内容
|
||||
logging.info(f"📚 检索到的上下文内容:\n{context_str}")
|
||||
return context_str
|
||||
except Exception as e:
|
||||
logging.error(f"从向量数据库检索时发生错误: {e}")
|
||||
@@ -633,7 +576,11 @@ class PyTreeGenerator:
|
||||
{"role": "user", "content": user_prompt}
|
||||
],
|
||||
temperature=0.0,
|
||||
response_format={"type": "json_object"}
|
||||
response_format={"type": "json_object"}, # 强制JSON输出,禁用思考功能
|
||||
max_tokens=self.classifier_max_tokens,
|
||||
# 禁用 Qwen3 模型的思考功能(通过 extra_body 传递)
|
||||
# 注意:如果 API 服务器不支持此参数,会忽略
|
||||
extra_body={"chat_template_kwargs": {"enable_thinking": False}}
|
||||
)
|
||||
class_str = classifier_resp.choices[0].message.content
|
||||
class_obj = json.loads(class_str)
|
||||
@@ -662,33 +609,115 @@ class PyTreeGenerator:
|
||||
final_user_prompt += augmentation
|
||||
else:
|
||||
logging.warning("未检索到上下文或检索失败,将使用原始用户提示词。")
|
||||
|
||||
# 构建完整的 final_prompt(准确反映实际发送给大模型的内容结构)
|
||||
# 注意:RAG检索结果被添加到 user prompt 中,而不是 system prompt
|
||||
# System Prompt: use_prompt(不包含RAG结果)
|
||||
# User Prompt: final_user_prompt(包含原始user_prompt + RAG检索结果)
|
||||
final_prompt = f"=== System Prompt ===\n{use_prompt}\n\n=== User Prompt ===\n{final_user_prompt}"
|
||||
for attempt in range(3):
|
||||
logging.info(f"--- 第 {attempt + 1}/3 次尝试生成Pytree ---")
|
||||
try:
|
||||
# 简单/复杂分流到不同模型与提示词
|
||||
client = self.simple_llm_client if mode == "simple" else self.complex_llm_client
|
||||
model_name = self.simple_model if mode == "simple" else self.complex_model
|
||||
response = client.chat.completions.create(
|
||||
model=model_name,
|
||||
messages=[
|
||||
# 始终强制JSON响应并禁用思考功能
|
||||
response_kwargs = {
|
||||
"model": model_name,
|
||||
"messages": [
|
||||
{"role": "system", "content": use_prompt},
|
||||
{"role": "user", "content": final_user_prompt}
|
||||
],
|
||||
temperature=0.1 if mode == "complex" else 0.0,
|
||||
response_format={"type": "json_object"}
|
||||
)
|
||||
pytree_str = response.choices[0].message.content
|
||||
"temperature": 0.1 if mode == "complex" else 0.0,
|
||||
"response_format": {"type": "json_object"}, # 始终强制JSON输出,禁用思考功能
|
||||
# 禁用 Qwen3 模型的思考功能(通过 extra_body 传递)
|
||||
# 注意:如果 API 服务器不支持此参数,会忽略
|
||||
"extra_body": {"chat_template_kwargs": {"enable_thinking": False}}
|
||||
}
|
||||
# 基于模式设定最大输出token数(直接在代码中配置)
|
||||
response_kwargs["max_tokens"] = self.simple_max_tokens if mode == "simple" else self.complex_max_tokens
|
||||
response = client.chat.completions.create(**response_kwargs)
|
||||
# 兼容可能存在的 reasoning_content 字段
|
||||
try:
|
||||
msg = response.choices[0].message
|
||||
msg_content = getattr(msg, "content", None)
|
||||
msg_reasoning = getattr(msg, "reasoning_content", None)
|
||||
except Exception:
|
||||
msg = response.choices[0]["message"] if isinstance(response.choices[0], dict) else None
|
||||
msg_content = (msg or {}).get("content") if isinstance(msg, dict) else None
|
||||
msg_reasoning = (msg or {}).get("reasoning_content") if isinstance(msg, dict) else None
|
||||
|
||||
combined_text = ""
|
||||
if isinstance(msg_reasoning, str) and msg_reasoning.strip():
|
||||
# 将 reasoning_content 包装为 <think>,便于统一解析
|
||||
combined_text += f"<think>\n{msg_reasoning}\n</think>\n"
|
||||
if isinstance(msg_content, str) and msg_content.strip():
|
||||
combined_text += msg_content
|
||||
pytree_str = combined_text if combined_text else (msg_content or "")
|
||||
raw_full_text_for_logging = pytree_str # 保存完整原文(含 <think>)以便失败时完整打印
|
||||
|
||||
# 提取 <think> 推理链内容(若存在)
|
||||
reasoning_text = None
|
||||
try:
|
||||
think_match = re.search(r"<think>([\s\S]*?)</think>", pytree_str)
|
||||
if think_match:
|
||||
reasoning_text = think_match.group(1).strip()
|
||||
# 去除推理文本后再尝试解析JSON
|
||||
pytree_str = re.sub(r"<think>[\s\S]*?</think>", "", pytree_str).strip()
|
||||
except Exception:
|
||||
reasoning_text = None
|
||||
# 单独捕获JSON解析错误并打印原始响应
|
||||
try:
|
||||
pytree_dict = json.loads(pytree_str)
|
||||
except json.JSONDecodeError as e:
|
||||
logging.error(f"❌ JSON解析失败(第 {attempt + 1}/3 次)。原始响应如下:\n{pytree_str}")
|
||||
logging.error(f"❌ JSON解析失败(第 {attempt + 1}/3 次)。\n—— 完整原始文本(含<think>) ——\n{raw_full_text_for_logging}")
|
||||
# 尝试打印响应对象的完整结构
|
||||
try:
|
||||
raw_response_dump = None
|
||||
if hasattr(response, 'model_dump_json'):
|
||||
raw_response_dump = response.model_dump_json(indent=2, exclude_none=False)
|
||||
elif hasattr(response, 'dict'):
|
||||
raw_response_dump = json.dumps(response.dict(), ensure_ascii=False, indent=2, default=str)
|
||||
else:
|
||||
# 兜底:尝试将choices与关键字段展开
|
||||
safe_obj = {
|
||||
"id": getattr(response, 'id', None),
|
||||
"model": getattr(response, 'model', None),
|
||||
"object": getattr(response, 'object', None),
|
||||
"usage": getattr(response, 'usage', None),
|
||||
"choices": [
|
||||
{
|
||||
"index": getattr(c, 'index', None),
|
||||
"finish_reason": getattr(c, 'finish_reason', None),
|
||||
"message": {
|
||||
"role": getattr(getattr(c, 'message', None), 'role', None),
|
||||
"content": getattr(getattr(c, 'message', None), 'content', None),
|
||||
"reasoning_content": getattr(getattr(c, 'message', None), 'reasoning_content', None)
|
||||
} if getattr(c, 'message', None) is not None else None
|
||||
}
|
||||
for c in getattr(response, 'choices', [])
|
||||
] if hasattr(response, 'choices') else None
|
||||
}
|
||||
raw_response_dump = json.dumps(safe_obj, ensure_ascii=False, indent=2, default=str)
|
||||
logging.error(f"—— 完整响应对象 ——\n{raw_response_dump}")
|
||||
except Exception as dump_e:
|
||||
try:
|
||||
logging.error(f"响应对象转储失败,repr如下:\n{repr(response)}")
|
||||
except Exception:
|
||||
pass
|
||||
continue
|
||||
|
||||
# 简单/复杂分别验证与返回
|
||||
if mode == "simple":
|
||||
try:
|
||||
jsonschema.validate(instance=pytree_dict, schema=self.simple_schema)
|
||||
# 手动检查:简单模式的root节点不能有children(或children必须是空数组)
|
||||
root_node = pytree_dict.get('root', {})
|
||||
if 'children' in root_node:
|
||||
children = root_node.get('children', [])
|
||||
if isinstance(children, list) and len(children) > 0:
|
||||
logging.warning(f"❌ 简单模式验证失败: root节点不能有children,但发现 {len(children)} 个子节点")
|
||||
continue
|
||||
logging.info("✅ 简单模式JSON Schema验证成功")
|
||||
except jsonschema.ValidationError as e:
|
||||
logging.warning(f"❌ 简单模式验证失败: {e.message}")
|
||||
@@ -696,56 +725,67 @@ class PyTreeGenerator:
|
||||
# 附加元信息并生成简单可视化(单动作)
|
||||
plan_id = str(uuid.uuid4())
|
||||
pytree_dict['plan_id'] = plan_id
|
||||
# 简单模式可视化:直接使用root节点
|
||||
# 简单模式可视化:使用root节点(已经是action类型)
|
||||
try:
|
||||
vis_filename = "py_tree.png"
|
||||
vis_path = os.path.join(self.vis_dir, vis_filename)
|
||||
_visualize_pytree(pytree_dict['root'], os.path.splitext(vis_path)[0])
|
||||
# 简单模式的root节点就是action节点,直接使用
|
||||
root_node = pytree_dict.get('root', {})
|
||||
_visualize_pytree(root_node, os.path.splitext(vis_path)[0])
|
||||
pytree_dict['visualization_url'] = f"/static/{vis_filename}"
|
||||
except Exception as e:
|
||||
logging.warning(f"简单模式可视化失败: {e}")
|
||||
|
||||
# 保存推理链(若有)
|
||||
try:
|
||||
if reasoning_text:
|
||||
reasoning_path = os.path.join(self.reasoning_dir, "reasoning_content.md")
|
||||
with open(reasoning_path, 'w', encoding='utf-8') as rf:
|
||||
rf.write(reasoning_text)
|
||||
logging.info(f"📝 推理链已保存: {reasoning_path}")
|
||||
# 终端预览(最多N行)
|
||||
try:
|
||||
lines = reasoning_text.splitlines()
|
||||
preview = "\n".join(lines[: self.reasoning_preview_lines])
|
||||
logging.info("🧠 推理链预览(前%d行):\n%s", self.reasoning_preview_lines, preview)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
logging.info("未在模型输出中发现 <think> 推理链片段。若需捕获,请设置 ENABLE_REASONING_CAPTURE=true 以放宽JSON强制格式。")
|
||||
except Exception as e:
|
||||
logging.warning(f"保存推理链Markdown失败: {e}")
|
||||
# 添加 final_prompt 到返回结果
|
||||
pytree_dict['final_prompt'] = final_prompt
|
||||
return pytree_dict
|
||||
|
||||
# 复杂模式回退:若模型误返回简单结构,则自动包装为含安全监控的行为树
|
||||
if mode == "complex" and isinstance(pytree_dict, dict) and 'root' not in pytree_dict:
|
||||
try:
|
||||
jsonschema.validate(instance=pytree_dict, schema=self.simple_schema)
|
||||
logging.warning("⚠️ 复杂模式生成了简单结构,触发自动包装为完整行为树的回退逻辑。")
|
||||
simple_action_obj = pytree_dict.get('action') or {}
|
||||
action_name = simple_action_obj.get('name')
|
||||
action_params = simple_action_obj.get('params') if isinstance(simple_action_obj.get('params'), dict) else {}
|
||||
# 复杂模式回退:若模型误返回简单结构(root是单个action),则自动包装为完整行为树
|
||||
if mode == "complex" and isinstance(pytree_dict, dict) and 'root' in pytree_dict:
|
||||
root_node = pytree_dict.get('root', {})
|
||||
# 检查是否是简单结构(root是单个action节点,没有children)
|
||||
if (root_node.get('type') == 'action' and
|
||||
('children' not in root_node or not root_node.get('children'))):
|
||||
try:
|
||||
jsonschema.validate(instance=pytree_dict, schema=self.simple_schema)
|
||||
logging.warning("⚠️ 复杂模式生成了简单结构(单个action),触发自动包装为完整行为树的回退逻辑。")
|
||||
action_name = root_node.get('name')
|
||||
action_params = root_node.get('params') if isinstance(root_node.get('params'), dict) else {}
|
||||
|
||||
safety_selector = {
|
||||
"type": "Selector",
|
||||
"name": "SafetyMonitor",
|
||||
"params": {"memory": True},
|
||||
"children": [
|
||||
{"type": "condition", "name": "battery_above", "params": {"threshold": 0.3}},
|
||||
{"type": "condition", "name": "gps_status", "params": {"min_satellites": 8}},
|
||||
{"type": "Sequence", "name": "EmergencyHandler", "children": [
|
||||
{"type": "action", "name": "emergency_return", "params": {"reason": "safety_breach"}},
|
||||
{"type": "action", "name": "land", "params": {"mode": "home"}}
|
||||
]}
|
||||
]
|
||||
}
|
||||
main_children = [{"type": "action", "name": action_name, "params": action_params}]
|
||||
if action_name != "land":
|
||||
main_children.append({"type": "action", "name": "land", "params": {"mode": "home"}})
|
||||
|
||||
main_children = [{"type": "action", "name": action_name, "params": action_params}]
|
||||
if action_name != "land":
|
||||
main_children.append({"type": "action", "name": "land", "params": {"mode": "home"}})
|
||||
|
||||
root_parallel = {
|
||||
"type": "Parallel",
|
||||
"name": "MissionWithSafety",
|
||||
"params": {"policy": "all_success"},
|
||||
"children": [
|
||||
{"type": "Sequence", "name": "MainTask", "children": main_children},
|
||||
safety_selector
|
||||
]
|
||||
}
|
||||
pytree_dict = {"root": root_parallel}
|
||||
except jsonschema.ValidationError:
|
||||
# 不符合简单结构,按正常复杂验证继续
|
||||
pass
|
||||
root_parallel = {
|
||||
"type": "Parallel",
|
||||
"name": "Mission",
|
||||
"params": {"policy": "all_success"},
|
||||
"children": [
|
||||
{"type": "Sequence", "name": "MainTask", "children": main_children}
|
||||
]
|
||||
}
|
||||
pytree_dict = {"root": root_parallel}
|
||||
except jsonschema.ValidationError:
|
||||
# 不符合简单结构,按正常复杂验证继续
|
||||
pass
|
||||
if _validate_pytree_with_schema(pytree_dict, self.schema):
|
||||
logging.info("✅ 成功生成并验证了Pytree")
|
||||
plan_id = str(uuid.uuid4())
|
||||
@@ -756,6 +796,27 @@ class PyTreeGenerator:
|
||||
vis_path = os.path.join(self.vis_dir, vis_filename)
|
||||
_visualize_pytree(pytree_dict['root'], os.path.splitext(vis_path)[0])
|
||||
pytree_dict['visualization_url'] = f"/static/{vis_filename}"
|
||||
|
||||
# 保存推理链(若有)
|
||||
try:
|
||||
if reasoning_text:
|
||||
reasoning_path = os.path.join(self.reasoning_dir, "reasoning_content.md")
|
||||
with open(reasoning_path, 'w', encoding='utf-8') as rf:
|
||||
rf.write(reasoning_text)
|
||||
logging.info(f"📝 推理链已保存: {reasoning_path}")
|
||||
# 终端预览(最多N行)
|
||||
try:
|
||||
lines = reasoning_text.splitlines()
|
||||
preview = "\n".join(lines[: self.reasoning_preview_lines])
|
||||
logging.info("🧠 推理链预览(前%d行):\n%s", self.reasoning_preview_lines, preview)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
logging.info("未在模型输出中发现 <think> 推理链片段。若需捕获,请设置 ENABLE_REASONING_CAPTURE=true 以放宽JSON强制格式。")
|
||||
except Exception as e:
|
||||
logging.warning(f"保存推理链Markdown失败: {e}")
|
||||
# 添加 final_prompt 到返回结果
|
||||
pytree_dict['final_prompt'] = final_prompt
|
||||
return pytree_dict
|
||||
else:
|
||||
# 打印未通过验证的Pytree以便排查
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
import rclpy
|
||||
from rclpy.action import ActionClient
|
||||
from rclpy.node import Node
|
||||
import json
|
||||
from typing import Dict, Any
|
||||
import logging
|
||||
|
||||
from drone_interfaces.action import ExecuteMission
|
||||
from .websocket_manager import websocket_manager
|
||||
|
||||
class MissionActionClient(Node):
|
||||
"""
|
||||
Interfaces with the drone's `ExecuteMission` ROS2 Action Server.
|
||||
"""
|
||||
def __init__(self):
|
||||
super().__init__('mission_action_client')
|
||||
self._action_client = ActionClient(self, ExecuteMission, 'execute_mission')
|
||||
self.get_logger().info("MissionActionClient initialized.")
|
||||
|
||||
def send_goal(self, py_tree: Dict[str, Any]):
|
||||
"""
|
||||
Sends the mission (py_tree) to the action server.
|
||||
"""
|
||||
if not self._action_client.server_is_ready():
|
||||
self.get_logger().error("Action server not available, goal not sent.")
|
||||
# Optionally, you could broadcast a status update to the frontend here
|
||||
return
|
||||
|
||||
self.get_logger().info("Received request to send goal to drone.")
|
||||
goal_msg = ExecuteMission.Goal()
|
||||
goal_msg.py_tree_json = json.dumps(py_tree)
|
||||
|
||||
self.get_logger().info(f"Sending goal to action server...")
|
||||
send_goal_future = self._action_client.send_goal_async(
|
||||
goal_msg,
|
||||
feedback_callback=self.feedback_callback
|
||||
)
|
||||
|
||||
send_goal_future.add_done_callback(self.goal_response_callback)
|
||||
|
||||
def goal_response_callback(self, future):
|
||||
goal_handle = future.result()
|
||||
if not goal_handle.accepted:
|
||||
self.get_logger().info('Goal rejected :(')
|
||||
return
|
||||
|
||||
self.get_logger().info('Goal accepted :)')
|
||||
|
||||
self._get_result_future = goal_handle.get_result_async()
|
||||
self._get_result_future.add_done_callback(self.get_result_callback)
|
||||
|
||||
def get_result_callback(self, future):
|
||||
result = future.result().result
|
||||
self.get_logger().info(f'Result: {{success: {result.success}, message: {result.message}}}')
|
||||
# Optionally, you can broadcast the final result via WebSocket here
|
||||
|
||||
def feedback_callback(self, feedback_msg):
|
||||
"""
|
||||
This callback is triggered by the action server.
|
||||
It forwards the status to the QGC plugin via the WebSocket manager in a thread-safe manner.
|
||||
"""
|
||||
feedback = feedback_msg.feedback
|
||||
feedback_payload = json.dumps({"node_id": feedback.node_id, "status": feedback.status})
|
||||
self.get_logger().info(f"Received feedback: {feedback_payload}")
|
||||
websocket_manager.broadcast(feedback_payload)
|
||||
|
||||
# Note: The rclpy.init() and spinning of the node will be handled in main.py
|
||||
@@ -22,7 +22,8 @@ class ConnectionManager:
|
||||
def broadcast(self, message: str):
|
||||
"""
|
||||
Thread-safely broadcasts a message to all active WebSocket connections.
|
||||
This method is designed to be called from a different thread (e.g., a ROS2 callback).
|
||||
This method is designed to be called from a different thread.
|
||||
(Note: ROS2 callback support has been removed as the project is decoupled from ROS2)
|
||||
"""
|
||||
if not self.loop:
|
||||
logging.error("Event loop not set in ConnectionManager. Cannot broadcast.")
|
||||
|
||||
248
backend_service/venv/bin/Activate.ps1
Executable file
248
backend_service/venv/bin/Activate.ps1
Executable file
@@ -0,0 +1,248 @@
|
||||
<#
|
||||
.Synopsis
|
||||
Activate a Python virtual environment for the current PowerShell session.
|
||||
|
||||
.Description
|
||||
Pushes the python executable for a virtual environment to the front of the
|
||||
$Env:PATH environment variable and sets the prompt to signify that you are
|
||||
in a Python virtual environment. Makes use of the command line switches as
|
||||
well as the `pyvenv.cfg` file values present in the virtual environment.
|
||||
|
||||
.Parameter VenvDir
|
||||
Path to the directory that contains the virtual environment to activate. The
|
||||
default value for this is the parent of the directory that the Activate.ps1
|
||||
script is located within.
|
||||
|
||||
.Parameter Prompt
|
||||
The prompt prefix to display when this virtual environment is activated. By
|
||||
default, this prompt is the name of the virtual environment folder (VenvDir)
|
||||
surrounded by parentheses and followed by a single space (ie. '(.venv) ').
|
||||
|
||||
.Example
|
||||
Activate.ps1
|
||||
Activates the Python virtual environment that contains the Activate.ps1 script.
|
||||
|
||||
.Example
|
||||
Activate.ps1 -Verbose
|
||||
Activates the Python virtual environment that contains the Activate.ps1 script,
|
||||
and shows extra information about the activation as it executes.
|
||||
|
||||
.Example
|
||||
Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
|
||||
Activates the Python virtual environment located in the specified location.
|
||||
|
||||
.Example
|
||||
Activate.ps1 -Prompt "MyPython"
|
||||
Activates the Python virtual environment that contains the Activate.ps1 script,
|
||||
and prefixes the current prompt with the specified string (surrounded in
|
||||
parentheses) while the virtual environment is active.
|
||||
|
||||
.Notes
|
||||
On Windows, it may be required to enable this Activate.ps1 script by setting the
|
||||
execution policy for the user. You can do this by issuing the following PowerShell
|
||||
command:
|
||||
|
||||
PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
|
||||
For more information on Execution Policies:
|
||||
https://go.microsoft.com/fwlink/?LinkID=135170
|
||||
|
||||
#>
|
||||
Param(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[String]
|
||||
$VenvDir,
|
||||
[Parameter(Mandatory = $false)]
|
||||
[String]
|
||||
$Prompt
|
||||
)
|
||||
|
||||
<# Function declarations --------------------------------------------------- #>
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Remove all shell session elements added by the Activate script, including the
|
||||
addition of the virtual environment's Python executable from the beginning of
|
||||
the PATH variable.
|
||||
|
||||
.Parameter NonDestructive
|
||||
If present, do not remove this function from the global namespace for the
|
||||
session.
|
||||
|
||||
#>
|
||||
function global:deactivate ([switch]$NonDestructive) {
|
||||
# Revert to original values
|
||||
|
||||
# The prior prompt:
|
||||
if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
|
||||
Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
|
||||
Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
|
||||
}
|
||||
|
||||
# The prior PYTHONHOME:
|
||||
if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
|
||||
Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
|
||||
Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
|
||||
}
|
||||
|
||||
# The prior PATH:
|
||||
if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
|
||||
Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
|
||||
Remove-Item -Path Env:_OLD_VIRTUAL_PATH
|
||||
}
|
||||
|
||||
# Just remove the VIRTUAL_ENV altogether:
|
||||
if (Test-Path -Path Env:VIRTUAL_ENV) {
|
||||
Remove-Item -Path env:VIRTUAL_ENV
|
||||
}
|
||||
|
||||
# Just remove VIRTUAL_ENV_PROMPT altogether.
|
||||
if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) {
|
||||
Remove-Item -Path env:VIRTUAL_ENV_PROMPT
|
||||
}
|
||||
|
||||
# Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
|
||||
if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
|
||||
Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
|
||||
}
|
||||
|
||||
# Leave deactivate function in the global namespace if requested:
|
||||
if (-not $NonDestructive) {
|
||||
Remove-Item -Path function:deactivate
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.Description
|
||||
Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
|
||||
given folder, and returns them in a map.
|
||||
|
||||
For each line in the pyvenv.cfg file, if that line can be parsed into exactly
|
||||
two strings separated by `=` (with any amount of whitespace surrounding the =)
|
||||
then it is considered a `key = value` line. The left hand string is the key,
|
||||
the right hand is the value.
|
||||
|
||||
If the value starts with a `'` or a `"` then the first and last character is
|
||||
stripped from the value before being captured.
|
||||
|
||||
.Parameter ConfigDir
|
||||
Path to the directory that contains the `pyvenv.cfg` file.
|
||||
#>
|
||||
function Get-PyVenvConfig(
|
||||
[String]
|
||||
$ConfigDir
|
||||
) {
|
||||
Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
|
||||
|
||||
# Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
|
||||
$pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
|
||||
|
||||
# An empty map will be returned if no config file is found.
|
||||
$pyvenvConfig = @{ }
|
||||
|
||||
if ($pyvenvConfigPath) {
|
||||
|
||||
Write-Verbose "File exists, parse `key = value` lines"
|
||||
$pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
|
||||
|
||||
$pyvenvConfigContent | ForEach-Object {
|
||||
$keyval = $PSItem -split "\s*=\s*", 2
|
||||
if ($keyval[0] -and $keyval[1]) {
|
||||
$val = $keyval[1]
|
||||
|
||||
# Remove extraneous quotations around a string value.
|
||||
if ("'""".Contains($val.Substring(0, 1))) {
|
||||
$val = $val.Substring(1, $val.Length - 2)
|
||||
}
|
||||
|
||||
$pyvenvConfig[$keyval[0]] = $val
|
||||
Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
|
||||
}
|
||||
}
|
||||
}
|
||||
return $pyvenvConfig
|
||||
}
|
||||
|
||||
|
||||
<# Begin Activate script --------------------------------------------------- #>
|
||||
|
||||
# Determine the containing directory of this script
|
||||
$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||
$VenvExecDir = Get-Item -Path $VenvExecPath
|
||||
|
||||
Write-Verbose "Activation script is located in path: '$VenvExecPath'"
|
||||
Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
|
||||
Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
|
||||
|
||||
# Set values required in priority: CmdLine, ConfigFile, Default
|
||||
# First, get the location of the virtual environment, it might not be
|
||||
# VenvExecDir if specified on the command line.
|
||||
if ($VenvDir) {
|
||||
Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
|
||||
}
|
||||
else {
|
||||
Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
|
||||
$VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
|
||||
Write-Verbose "VenvDir=$VenvDir"
|
||||
}
|
||||
|
||||
# Next, read the `pyvenv.cfg` file to determine any required value such
|
||||
# as `prompt`.
|
||||
$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
|
||||
|
||||
# Next, set the prompt from the command line, or the config file, or
|
||||
# just use the name of the virtual environment folder.
|
||||
if ($Prompt) {
|
||||
Write-Verbose "Prompt specified as argument, using '$Prompt'"
|
||||
}
|
||||
else {
|
||||
Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
|
||||
if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
|
||||
Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
|
||||
$Prompt = $pyvenvCfg['prompt'];
|
||||
}
|
||||
else {
|
||||
Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)"
|
||||
Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
|
||||
$Prompt = Split-Path -Path $venvDir -Leaf
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose "Prompt = '$Prompt'"
|
||||
Write-Verbose "VenvDir='$VenvDir'"
|
||||
|
||||
# Deactivate any currently active virtual environment, but leave the
|
||||
# deactivate function in place.
|
||||
deactivate -nondestructive
|
||||
|
||||
# Now set the environment variable VIRTUAL_ENV, used by many tools to determine
|
||||
# that there is an activated venv.
|
||||
$env:VIRTUAL_ENV = $VenvDir
|
||||
|
||||
$env:VIRTUAL_ENV_PROMPT = $Prompt
|
||||
|
||||
if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
|
||||
|
||||
Write-Verbose "Setting prompt to '$Prompt'"
|
||||
|
||||
# Set the prompt to include the env name
|
||||
# Make sure _OLD_VIRTUAL_PROMPT is global
|
||||
function global:_OLD_VIRTUAL_PROMPT { "" }
|
||||
Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
|
||||
New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
|
||||
|
||||
function global:prompt {
|
||||
Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
|
||||
_OLD_VIRTUAL_PROMPT
|
||||
}
|
||||
}
|
||||
|
||||
# Clear PYTHONHOME
|
||||
if (Test-Path -Path Env:PYTHONHOME) {
|
||||
Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
|
||||
Remove-Item -Path Env:PYTHONHOME
|
||||
}
|
||||
|
||||
# Add the venv to the PATH
|
||||
Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
|
||||
$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"
|
||||
76
backend_service/venv/bin/activate
Executable file
76
backend_service/venv/bin/activate
Executable file
@@ -0,0 +1,76 @@
|
||||
# This file must be used with "source bin/activate" *from bash*
|
||||
# You cannot run it directly
|
||||
|
||||
deactivate () {
|
||||
# reset old environment variables
|
||||
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
|
||||
PATH="${_OLD_VIRTUAL_PATH:-}"
|
||||
export PATH
|
||||
unset _OLD_VIRTUAL_PATH
|
||||
fi
|
||||
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
|
||||
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
|
||||
export PYTHONHOME
|
||||
unset _OLD_VIRTUAL_PYTHONHOME
|
||||
fi
|
||||
|
||||
# Call hash to forget past locations. Without forgetting
|
||||
# past locations the $PATH changes we made may not be respected.
|
||||
# See "man bash" for more details. hash is usually a builtin of your shell
|
||||
hash -r 2> /dev/null
|
||||
|
||||
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
|
||||
PS1="${_OLD_VIRTUAL_PS1:-}"
|
||||
export PS1
|
||||
unset _OLD_VIRTUAL_PS1
|
||||
fi
|
||||
|
||||
unset VIRTUAL_ENV
|
||||
unset VIRTUAL_ENV_PROMPT
|
||||
if [ ! "${1:-}" = "nondestructive" ] ; then
|
||||
# Self destruct!
|
||||
unset -f deactivate
|
||||
fi
|
||||
}
|
||||
|
||||
# unset irrelevant variables
|
||||
deactivate nondestructive
|
||||
|
||||
# on Windows, a path can contain colons and backslashes and has to be converted:
|
||||
case "$(uname)" in
|
||||
CYGWIN*|MSYS*|MINGW*)
|
||||
# transform D:\path\to\venv to /d/path/to/venv on MSYS and MINGW
|
||||
# and to /cygdrive/d/path/to/venv on Cygwin
|
||||
VIRTUAL_ENV=$(cygpath /home/huangfukk/DronePlanning/backend_service/venv)
|
||||
export VIRTUAL_ENV
|
||||
;;
|
||||
*)
|
||||
# use the path as-is
|
||||
export VIRTUAL_ENV=/home/huangfukk/DronePlanning/backend_service/venv
|
||||
;;
|
||||
esac
|
||||
|
||||
_OLD_VIRTUAL_PATH="$PATH"
|
||||
PATH="$VIRTUAL_ENV/"bin":$PATH"
|
||||
export PATH
|
||||
|
||||
VIRTUAL_ENV_PROMPT=venv
|
||||
export VIRTUAL_ENV_PROMPT
|
||||
|
||||
# unset PYTHONHOME if set
|
||||
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
|
||||
# could use `if (set -u; : $PYTHONHOME) ;` in bash
|
||||
if [ -n "${PYTHONHOME:-}" ] ; then
|
||||
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
|
||||
unset PYTHONHOME
|
||||
fi
|
||||
|
||||
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
|
||||
_OLD_VIRTUAL_PS1="${PS1:-}"
|
||||
PS1="("venv") ${PS1:-}"
|
||||
export PS1
|
||||
fi
|
||||
|
||||
# Call hash to forget past commands. Without forgetting
|
||||
# past commands the $PATH changes we made may not be respected
|
||||
hash -r 2> /dev/null
|
||||
27
backend_service/venv/bin/activate.csh
Executable file
27
backend_service/venv/bin/activate.csh
Executable file
@@ -0,0 +1,27 @@
|
||||
# This file must be used with "source bin/activate.csh" *from csh*.
|
||||
# You cannot run it directly.
|
||||
|
||||
# Created by Davide Di Blasi <davidedb@gmail.com>.
|
||||
# Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
|
||||
|
||||
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate'
|
||||
|
||||
# Unset irrelevant variables.
|
||||
deactivate nondestructive
|
||||
|
||||
setenv VIRTUAL_ENV /home/huangfukk/DronePlanning/backend_service/venv
|
||||
|
||||
set _OLD_VIRTUAL_PATH="$PATH"
|
||||
setenv PATH "$VIRTUAL_ENV/"bin":$PATH"
|
||||
setenv VIRTUAL_ENV_PROMPT venv
|
||||
|
||||
|
||||
set _OLD_VIRTUAL_PROMPT="$prompt"
|
||||
|
||||
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
|
||||
set prompt = "("venv") $prompt:q"
|
||||
endif
|
||||
|
||||
alias pydoc python -m pydoc
|
||||
|
||||
rehash
|
||||
69
backend_service/venv/bin/activate.fish
Executable file
69
backend_service/venv/bin/activate.fish
Executable file
@@ -0,0 +1,69 @@
|
||||
# This file must be used with "source <venv>/bin/activate.fish" *from fish*
|
||||
# (https://fishshell.com/). You cannot run it directly.
|
||||
|
||||
function deactivate -d "Exit virtual environment and return to normal shell environment"
|
||||
# reset old environment variables
|
||||
if test -n "$_OLD_VIRTUAL_PATH"
|
||||
set -gx PATH $_OLD_VIRTUAL_PATH
|
||||
set -e _OLD_VIRTUAL_PATH
|
||||
end
|
||||
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
|
||||
set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
|
||||
set -e _OLD_VIRTUAL_PYTHONHOME
|
||||
end
|
||||
|
||||
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
|
||||
set -e _OLD_FISH_PROMPT_OVERRIDE
|
||||
# prevents error when using nested fish instances (Issue #93858)
|
||||
if functions -q _old_fish_prompt
|
||||
functions -e fish_prompt
|
||||
functions -c _old_fish_prompt fish_prompt
|
||||
functions -e _old_fish_prompt
|
||||
end
|
||||
end
|
||||
|
||||
set -e VIRTUAL_ENV
|
||||
set -e VIRTUAL_ENV_PROMPT
|
||||
if test "$argv[1]" != "nondestructive"
|
||||
# Self-destruct!
|
||||
functions -e deactivate
|
||||
end
|
||||
end
|
||||
|
||||
# Unset irrelevant variables.
|
||||
deactivate nondestructive
|
||||
|
||||
set -gx VIRTUAL_ENV /home/huangfukk/DronePlanning/backend_service/venv
|
||||
|
||||
set -gx _OLD_VIRTUAL_PATH $PATH
|
||||
set -gx PATH "$VIRTUAL_ENV/"bin $PATH
|
||||
set -gx VIRTUAL_ENV_PROMPT venv
|
||||
|
||||
# Unset PYTHONHOME if set.
|
||||
if set -q PYTHONHOME
|
||||
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
|
||||
set -e PYTHONHOME
|
||||
end
|
||||
|
||||
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
|
||||
# fish uses a function instead of an env var to generate the prompt.
|
||||
|
||||
# Save the current fish_prompt function as the function _old_fish_prompt.
|
||||
functions -c fish_prompt _old_fish_prompt
|
||||
|
||||
# With the original prompt function renamed, we can override with our own.
|
||||
function fish_prompt
|
||||
# Save the return status of the last command.
|
||||
set -l old_status $status
|
||||
|
||||
# Output the venv prompt; color taken from the blue of the Python logo.
|
||||
printf "%s(%s)%s " (set_color 4B8BBE) venv (set_color normal)
|
||||
|
||||
# Restore the return status of the previous command.
|
||||
echo "exit $old_status" | .
|
||||
# Output the original/"old" prompt.
|
||||
_old_fish_prompt
|
||||
end
|
||||
|
||||
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
|
||||
end
|
||||
7
backend_service/venv/bin/chroma
Executable file
7
backend_service/venv/bin/chroma
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from chromadb.cli.cli import app
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(app())
|
||||
7
backend_service/venv/bin/coloredlogs
Executable file
7
backend_service/venv/bin/coloredlogs
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from coloredlogs.cli import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/dashscope
Executable file
7
backend_service/venv/bin/dashscope
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from dashscope.cli import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/distro
Executable file
7
backend_service/venv/bin/distro
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from distro.distro import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/dotenv
Executable file
7
backend_service/venv/bin/dotenv
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from dotenv.__main__ import cli
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(cli())
|
||||
7
backend_service/venv/bin/f2py
Executable file
7
backend_service/venv/bin/f2py
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from numpy.f2py.f2py2e import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/fastapi
Executable file
7
backend_service/venv/bin/fastapi
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from fastapi.cli import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/hf
Executable file
7
backend_service/venv/bin/hf
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from huggingface_hub.cli.hf import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/httpx
Executable file
7
backend_service/venv/bin/httpx
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from httpx import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/humanfriendly
Executable file
7
backend_service/venv/bin/humanfriendly
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from humanfriendly.cli import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/isympy
Executable file
7
backend_service/venv/bin/isympy
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from isympy import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/json_repair
Executable file
7
backend_service/venv/bin/json_repair
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from json_repair.__main__ import cli
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(cli())
|
||||
7
backend_service/venv/bin/jsonschema
Executable file
7
backend_service/venv/bin/jsonschema
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from jsonschema.cli import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/markdown-it
Executable file
7
backend_service/venv/bin/markdown-it
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from markdown_it.cli.parse import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/mcp
Executable file
7
backend_service/venv/bin/mcp
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from mcp.cli import app
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(app())
|
||||
7
backend_service/venv/bin/normalizer
Executable file
7
backend_service/venv/bin/normalizer
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from charset_normalizer.cli import cli_detect
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(cli_detect())
|
||||
7
backend_service/venv/bin/numpy-config
Executable file
7
backend_service/venv/bin/numpy-config
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from numpy._configtool import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/onnxruntime_test
Executable file
7
backend_service/venv/bin/onnxruntime_test
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from onnxruntime.tools.onnxruntime_test import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/openai
Executable file
7
backend_service/venv/bin/openai
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from openai.cli import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
8
backend_service/venv/bin/pip
Executable file
8
backend_service/venv/bin/pip
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
from pip._internal.cli.main import main
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(main())
|
||||
8
backend_service/venv/bin/pip3
Executable file
8
backend_service/venv/bin/pip3
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
from pip._internal.cli.main import main
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(main())
|
||||
8
backend_service/venv/bin/pip3.13
Executable file
8
backend_service/venv/bin/pip3.13
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
from pip._internal.cli.main import main
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/pybase64
Executable file
7
backend_service/venv/bin/pybase64
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from pybase64.__main__ import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/pygmentize
Executable file
7
backend_service/venv/bin/pygmentize
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from pygments.cmdline import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/pyjson5
Executable file
7
backend_service/venv/bin/pyjson5
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from json5.tool import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/pyproject-build
Executable file
7
backend_service/venv/bin/pyproject-build
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from build.__main__ import entrypoint
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(entrypoint())
|
||||
7
backend_service/venv/bin/pyrsa-decrypt
Executable file
7
backend_service/venv/bin/pyrsa-decrypt
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from rsa.cli import decrypt
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(decrypt())
|
||||
7
backend_service/venv/bin/pyrsa-encrypt
Executable file
7
backend_service/venv/bin/pyrsa-encrypt
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from rsa.cli import encrypt
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(encrypt())
|
||||
7
backend_service/venv/bin/pyrsa-keygen
Executable file
7
backend_service/venv/bin/pyrsa-keygen
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from rsa.cli import keygen
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(keygen())
|
||||
7
backend_service/venv/bin/pyrsa-priv2pub
Executable file
7
backend_service/venv/bin/pyrsa-priv2pub
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from rsa.util import private_to_public
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(private_to_public())
|
||||
7
backend_service/venv/bin/pyrsa-sign
Executable file
7
backend_service/venv/bin/pyrsa-sign
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from rsa.cli import sign
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(sign())
|
||||
7
backend_service/venv/bin/pyrsa-verify
Executable file
7
backend_service/venv/bin/pyrsa-verify
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from rsa.cli import verify
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(verify())
|
||||
1
backend_service/venv/bin/python
Symbolic link
1
backend_service/venv/bin/python
Symbolic link
@@ -0,0 +1 @@
|
||||
python3
|
||||
1
backend_service/venv/bin/python3
Symbolic link
1
backend_service/venv/bin/python3
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/huangfukk/miniconda3/bin/python3
|
||||
1
backend_service/venv/bin/python3.13
Symbolic link
1
backend_service/venv/bin/python3.13
Symbolic link
@@ -0,0 +1 @@
|
||||
python3
|
||||
7
backend_service/venv/bin/shortuuid
Executable file
7
backend_service/venv/bin/shortuuid
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from shortuuid.cli import cli
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(cli())
|
||||
7
backend_service/venv/bin/tiny-agents
Executable file
7
backend_service/venv/bin/tiny-agents
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from huggingface_hub.inference._mcp.cli import app
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(app())
|
||||
7
backend_service/venv/bin/tqdm
Executable file
7
backend_service/venv/bin/tqdm
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from tqdm.cli import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/typer
Executable file
7
backend_service/venv/bin/typer
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from typer.cli import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/uvicorn
Executable file
7
backend_service/venv/bin/uvicorn
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from uvicorn.main import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/watchfiles
Executable file
7
backend_service/venv/bin/watchfiles
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from watchfiles.cli import cli
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(cli())
|
||||
7
backend_service/venv/bin/websockets
Executable file
7
backend_service/venv/bin/websockets
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from websockets.cli import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
7
backend_service/venv/bin/wsdump
Executable file
7
backend_service/venv/bin/wsdump
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||
import sys
|
||||
from websocket._wsdump import main
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[0].endswith('.exe'):
|
||||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
29
backend_service/venv/lib/python3.13/site-packages/COPYING
Normal file
29
backend_service/venv/lib/python3.13/site-packages/COPYING
Normal file
@@ -0,0 +1,29 @@
|
||||
Copyright (c) 2011, Stavros Korokithakis
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of Stochastic Technologies nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,7 @@
|
||||
Authors
|
||||
=======
|
||||
|
||||
``pyjwt`` is currently written and maintained by `Jose Padilla <https://github.com/jpadilla>`_.
|
||||
Originally written and maintained by `Jeff Lindsay <https://github.com/progrium>`_.
|
||||
|
||||
A full list of contributors can be found on GitHub’s `overview <https://github.com/jpadilla/pyjwt/graphs/contributors>`_.
|
||||
@@ -0,0 +1 @@
|
||||
pip
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2022 José Padilla
|
||||
|
||||
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,106 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: PyJWT
|
||||
Version: 2.10.1
|
||||
Summary: JSON Web Token implementation in Python
|
||||
Author-email: Jose Padilla <hello@jpadilla.com>
|
||||
License: MIT
|
||||
Project-URL: Homepage, https://github.com/jpadilla/pyjwt
|
||||
Keywords: json,jwt,security,signing,token,web
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Natural Language :: English
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3 :: Only
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Programming Language :: Python :: 3.13
|
||||
Classifier: Topic :: Utilities
|
||||
Requires-Python: >=3.9
|
||||
Description-Content-Type: text/x-rst
|
||||
License-File: LICENSE
|
||||
License-File: AUTHORS.rst
|
||||
Provides-Extra: crypto
|
||||
Requires-Dist: cryptography>=3.4.0; extra == "crypto"
|
||||
Provides-Extra: dev
|
||||
Requires-Dist: coverage[toml]==5.0.4; extra == "dev"
|
||||
Requires-Dist: cryptography>=3.4.0; extra == "dev"
|
||||
Requires-Dist: pre-commit; extra == "dev"
|
||||
Requires-Dist: pytest<7.0.0,>=6.0.0; extra == "dev"
|
||||
Requires-Dist: sphinx; extra == "dev"
|
||||
Requires-Dist: sphinx-rtd-theme; extra == "dev"
|
||||
Requires-Dist: zope.interface; extra == "dev"
|
||||
Provides-Extra: docs
|
||||
Requires-Dist: sphinx; extra == "docs"
|
||||
Requires-Dist: sphinx-rtd-theme; extra == "docs"
|
||||
Requires-Dist: zope.interface; extra == "docs"
|
||||
Provides-Extra: tests
|
||||
Requires-Dist: coverage[toml]==5.0.4; extra == "tests"
|
||||
Requires-Dist: pytest<7.0.0,>=6.0.0; extra == "tests"
|
||||
|
||||
PyJWT
|
||||
=====
|
||||
|
||||
.. image:: https://github.com/jpadilla/pyjwt/workflows/CI/badge.svg
|
||||
:target: https://github.com/jpadilla/pyjwt/actions?query=workflow%3ACI
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/pyjwt.svg
|
||||
:target: https://pypi.python.org/pypi/pyjwt
|
||||
|
||||
.. image:: https://codecov.io/gh/jpadilla/pyjwt/branch/master/graph/badge.svg
|
||||
:target: https://codecov.io/gh/jpadilla/pyjwt
|
||||
|
||||
.. image:: https://readthedocs.org/projects/pyjwt/badge/?version=stable
|
||||
:target: https://pyjwt.readthedocs.io/en/stable/
|
||||
|
||||
A Python implementation of `RFC 7519 <https://tools.ietf.org/html/rfc7519>`_. Original implementation was written by `@progrium <https://github.com/progrium>`_.
|
||||
|
||||
Sponsor
|
||||
-------
|
||||
|
||||
.. |auth0-logo| image:: https://github.com/user-attachments/assets/ee98379e-ee76-4bcb-943a-e25c4ea6d174
|
||||
:width: 160px
|
||||
|
||||
+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| |auth0-logo| | If you want to quickly add secure token-based authentication to Python projects, feel free to check Auth0's Python SDK and free plan at `auth0.com/signup <https://auth0.com/signup?utm_source=external_sites&utm_medium=pyjwt&utm_campaign=devn_signup>`_. |
|
||||
+--------------+-----------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
Installing
|
||||
----------
|
||||
|
||||
Install with **pip**:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install PyJWT
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import jwt
|
||||
>>> encoded = jwt.encode({"some": "payload"}, "secret", algorithm="HS256")
|
||||
>>> print(encoded)
|
||||
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg
|
||||
>>> jwt.decode(encoded, "secret", algorithms=["HS256"])
|
||||
{'some': 'payload'}
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
View the full docs online at https://pyjwt.readthedocs.io/en/stable/
|
||||
|
||||
|
||||
Tests
|
||||
-----
|
||||
|
||||
You can run tests from the project root after cloning with:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ tox
|
||||
@@ -0,0 +1,32 @@
|
||||
PyJWT-2.10.1.dist-info/AUTHORS.rst,sha256=klzkNGECnu2_VY7At89_xLBF3vUSDruXk3xwgUBxzwc,322
|
||||
PyJWT-2.10.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
PyJWT-2.10.1.dist-info/LICENSE,sha256=eXp6ICMdTEM-nxkR2xcx0GtYKLmPSZgZoDT3wPVvXOU,1085
|
||||
PyJWT-2.10.1.dist-info/METADATA,sha256=EkewF6D6KU8SGaaQzVYfxUUU1P_gs_dp1pYTkoYvAx8,3990
|
||||
PyJWT-2.10.1.dist-info/RECORD,,
|
||||
PyJWT-2.10.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
||||
PyJWT-2.10.1.dist-info/top_level.txt,sha256=RP5DHNyJbMq2ka0FmfTgoSaQzh7e3r5XuCWCO8a00k8,4
|
||||
jwt/__init__.py,sha256=VB2vFKuboTjcDGeZ8r-UqK_dz3NsQSQEqySSICby8Xg,1711
|
||||
jwt/__pycache__/__init__.cpython-313.pyc,,
|
||||
jwt/__pycache__/algorithms.cpython-313.pyc,,
|
||||
jwt/__pycache__/api_jwk.cpython-313.pyc,,
|
||||
jwt/__pycache__/api_jws.cpython-313.pyc,,
|
||||
jwt/__pycache__/api_jwt.cpython-313.pyc,,
|
||||
jwt/__pycache__/exceptions.cpython-313.pyc,,
|
||||
jwt/__pycache__/help.cpython-313.pyc,,
|
||||
jwt/__pycache__/jwk_set_cache.cpython-313.pyc,,
|
||||
jwt/__pycache__/jwks_client.cpython-313.pyc,,
|
||||
jwt/__pycache__/types.cpython-313.pyc,,
|
||||
jwt/__pycache__/utils.cpython-313.pyc,,
|
||||
jwt/__pycache__/warnings.cpython-313.pyc,,
|
||||
jwt/algorithms.py,sha256=cKr-XEioe0mBtqJMCaHEswqVOA1Z8Purt5Sb3Bi-5BE,30409
|
||||
jwt/api_jwk.py,sha256=6F1r7rmm8V5qEnBKA_xMjS9R7VoANe1_BL1oD2FrAjE,4451
|
||||
jwt/api_jws.py,sha256=aM8vzqQf6mRrAw7bRy-Moj_pjWsKSVQyYK896AfMjJU,11762
|
||||
jwt/api_jwt.py,sha256=OGT4hok1l5A6FH_KdcrU5g6u6EQ8B7em0r9kGM9SYgA,14512
|
||||
jwt/exceptions.py,sha256=bUIOJ-v9tjopTLS-FYOTc3kFx5WP5IZt7ksN_HE1G9Q,1211
|
||||
jwt/help.py,sha256=vFdNzjQoAch04XCMYpCkyB2blaqHAGAqQrtf9nSPkdk,1808
|
||||
jwt/jwk_set_cache.py,sha256=hBKmN-giU7-G37L_XKgc_OZu2ah4wdbj1ZNG_GkoSE8,959
|
||||
jwt/jwks_client.py,sha256=p9b-IbQqo2tEge9Zit3oSPBFNePqwho96VLbnUrHUWs,4259
|
||||
jwt/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
jwt/types.py,sha256=VnhGv_VFu5a7_mrPoSCB7HaNLrJdhM8Sq1sSfEg0gLU,99
|
||||
jwt/utils.py,sha256=hxOjvDBheBYhz-RIPiEz7Q88dSUSTMzEdKE_Ww2VdJw,3640
|
||||
jwt/warnings.py,sha256=50XWOnyNsIaqzUJTk6XHNiIDykiL763GYA92MjTKmok,59
|
||||
@@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: setuptools (75.6.0)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
jwt
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -0,0 +1,33 @@
|
||||
# This is a stub package designed to roughly emulate the _yaml
|
||||
# extension module, which previously existed as a standalone module
|
||||
# and has been moved into the `yaml` package namespace.
|
||||
# It does not perfectly mimic its old counterpart, but should get
|
||||
# close enough for anyone who's relying on it even when they shouldn't.
|
||||
import yaml
|
||||
|
||||
# in some circumstances, the yaml module we imoprted may be from a different version, so we need
|
||||
# to tread carefully when poking at it here (it may not have the attributes we expect)
|
||||
if not getattr(yaml, '__with_libyaml__', False):
|
||||
from sys import version_info
|
||||
|
||||
exc = ModuleNotFoundError if version_info >= (3, 6) else ImportError
|
||||
raise exc("No module named '_yaml'")
|
||||
else:
|
||||
from yaml._yaml import *
|
||||
import warnings
|
||||
warnings.warn(
|
||||
'The _yaml extension module is now located at yaml._yaml'
|
||||
' and its location is subject to change. To use the'
|
||||
' LibYAML-based parser and emitter, import from `yaml`:'
|
||||
' `from yaml import CLoader as Loader, CDumper as Dumper`.',
|
||||
DeprecationWarning
|
||||
)
|
||||
del warnings
|
||||
# Don't `del yaml` here because yaml is actually an existing
|
||||
# namespace member of _yaml.
|
||||
|
||||
__name__ = '_yaml'
|
||||
# If the module is top-level (i.e. not a part of any specific package)
|
||||
# then the attribute should be set to ''.
|
||||
# https://docs.python.org/3.8/library/types.html
|
||||
__package__ = ''
|
||||
@@ -0,0 +1 @@
|
||||
pip
|
||||
@@ -0,0 +1,547 @@
|
||||
Metadata-Version: 2.4
|
||||
Name: agentscope
|
||||
Version: 1.0.7
|
||||
Summary: AgentScope: A Flexible yet Robust Multi-Agent Platform.
|
||||
Author-email: SysML team of Alibaba Tongyi Lab <gaodawei.gdw@alibaba-inc.com>
|
||||
License-Expression: Apache-2.0
|
||||
Project-URL: Homepage, https://github.com/agentscope-ai/agentscope
|
||||
Project-URL: Documentation, https://doc.agentscope.io/
|
||||
Project-URL: Repository, https://github.com/agentscope-ai/agentscope
|
||||
Keywords: deep-learning,multi agents,agents
|
||||
Classifier: Development Status :: 4 - Beta
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Intended Audience :: Science/Research
|
||||
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
||||
Requires-Python: >=3.10
|
||||
Description-Content-Type: text/markdown
|
||||
License-File: LICENSE
|
||||
Requires-Dist: aioitertools
|
||||
Requires-Dist: anthropic
|
||||
Requires-Dist: dashscope
|
||||
Requires-Dist: docstring_parser
|
||||
Requires-Dist: json5
|
||||
Requires-Dist: json_repair
|
||||
Requires-Dist: mcp>=1.13
|
||||
Requires-Dist: numpy
|
||||
Requires-Dist: openai
|
||||
Requires-Dist: python-datauri
|
||||
Requires-Dist: opentelemetry-api
|
||||
Requires-Dist: opentelemetry-sdk
|
||||
Requires-Dist: opentelemetry-exporter-otlp
|
||||
Requires-Dist: python-socketio
|
||||
Requires-Dist: shortuuid
|
||||
Requires-Dist: tiktoken
|
||||
Requires-Dist: sounddevice
|
||||
Provides-Extra: full
|
||||
Requires-Dist: ollama>=0.5.4; extra == "full"
|
||||
Requires-Dist: google-genai; extra == "full"
|
||||
Requires-Dist: Pillow; extra == "full"
|
||||
Requires-Dist: transformers; extra == "full"
|
||||
Requires-Dist: jinja2; extra == "full"
|
||||
Requires-Dist: ray; extra == "full"
|
||||
Requires-Dist: mem0ai; extra == "full"
|
||||
Requires-Dist: packaging; extra == "full"
|
||||
Requires-Dist: pypdf; extra == "full"
|
||||
Requires-Dist: python-docx; extra == "full"
|
||||
Requires-Dist: nltk; extra == "full"
|
||||
Requires-Dist: qdrant-client; extra == "full"
|
||||
Provides-Extra: dev
|
||||
Requires-Dist: agentscope[full]; extra == "dev"
|
||||
Requires-Dist: pre-commit; extra == "dev"
|
||||
Requires-Dist: pytest; extra == "dev"
|
||||
Requires-Dist: sphinx-gallery; extra == "dev"
|
||||
Requires-Dist: furo; extra == "dev"
|
||||
Requires-Dist: myst_parser; extra == "dev"
|
||||
Requires-Dist: matplotlib; extra == "dev"
|
||||
Requires-Dist: pymilvus[milvus_lite]; extra == "dev"
|
||||
Requires-Dist: reme-ai>=0.1.10.7; python_full_version >= "3.12" and extra == "dev"
|
||||
Dynamic: license-file
|
||||
|
||||
[**中文主页**](https://github.com/agentscope-ai/agentscope/blob/main/README_zh.md) | [**Tutorial**](https://doc.agentscope.io/) | [**Roadmap**](https://github.com/agentscope-ai/agentscope/blob/main/docs/roadmap.md) | [**FAQ**](https://doc.agentscope.io/tutorial/faq.html)
|
||||
|
||||
<p align="center">
|
||||
<img
|
||||
src="https://img.alicdn.com/imgextra/i1/O1CN01nTg6w21NqT5qFKH1u_!!6000000001621-55-tps-550-550.svg"
|
||||
alt="AgentScope Logo"
|
||||
width="200"
|
||||
/>
|
||||
</p>
|
||||
|
||||
<h2 align="center">AgentScope: Agent-Oriented Programming for Building LLM Applications</h2>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://arxiv.org/abs/2402.14034">
|
||||
<img
|
||||
src="https://img.shields.io/badge/cs.MA-2402.14034-B31C1C?logo=arxiv&logoColor=B31C1C"
|
||||
alt="arxiv"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://pypi.org/project/agentscope/">
|
||||
<img
|
||||
src="https://img.shields.io/badge/python-3.10+-blue?logo=python"
|
||||
alt="pypi"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://pypi.org/project/agentscope/">
|
||||
<img
|
||||
src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fpypi.org%2Fpypi%2Fagentscope%2Fjson&query=%24.info.version&prefix=v&logo=pypi&label=version"
|
||||
alt="pypi"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://doc.agentscope.io/">
|
||||
<img
|
||||
src="https://img.shields.io/badge/Docs-English%7C%E4%B8%AD%E6%96%87-blue?logo=markdown"
|
||||
alt="docs"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://agentscope.io/">
|
||||
<img
|
||||
src="https://img.shields.io/badge/GUI-AgentScope_Studio-blue?logo=look&logoColor=green&color=dark-green"
|
||||
alt="workstation"
|
||||
/>
|
||||
</a>
|
||||
<a href="./LICENSE">
|
||||
<img
|
||||
src="https://img.shields.io/badge/license-Apache--2.0-black"
|
||||
alt="license"
|
||||
/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://trendshift.io/api/badge/repositories/10079" alt="modelscope%2Fagentscope | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/>
|
||||
</p>
|
||||
|
||||
## ✨ Why AgentScope?
|
||||
|
||||
Easy for beginners, powerful for experts.
|
||||
|
||||
<p align="center">
|
||||
<img src="./assets/images/agentscope_v1_0822.png" alt="AgentScope Framework" width="80%"/>
|
||||
</p>
|
||||
|
||||
- **Transparent to Developers**: Transparent is our **FIRST principle**. Prompt engineering, API invocation, agent building, workflow orchestration, all are visible and controllable for developers. No deep encapsulation or implicit magic.
|
||||
- **[Realtime Steering](https://doc.agentscope.io/tutorial/task_agent.html#realtime-steering)**: Native support for realtime interruption and customized handling.
|
||||
- **More Agentic**: Support [agentic tools management](https://doc.agentscope.io/tutorial/task_tool.html), [agentic long-term memory control](https://doc.agentscope.io/tutorial/task_long_term_memory.html) and agentic RAG, etc.
|
||||
- **Model Agnostic**: Programming once, run with all models.
|
||||
- **LEGO-style Agent Building**: All components are **modular** and **independent**.
|
||||
- **Multi-Agent Oriented**: Designed for **multi-agent**, **explicit** message passing and workflow orchestration, NO deep encapsulation.
|
||||
- **Highly Customizable**: Tools, prompt, agent, workflow, third-party libs & visualization, customization is encouraged everywhere.
|
||||
|
||||
Quick overview of important features in **AgentScope 1.0**:
|
||||
|
||||
| Module | Feature | Tutorial |
|
||||
|------------|------------------------------------------------------------------------------------|-------------------------------------------------------------------------|
|
||||
| model | Support async invocation | [Model](https://doc.agentscope.io/tutorial/task_model.html) |
|
||||
| | Support reasoning model | |
|
||||
| | Support streaming/non-streaming returns | |
|
||||
| tool | Support async/sync tool functions | [Tool](https://doc.agentscope.io/tutorial/task_tool.html) |
|
||||
| | Support streaming/non-streaming returns | |
|
||||
| | Support user interruption | |
|
||||
| | Support post-processing | |
|
||||
| | Support group-wise tools management | |
|
||||
| | Support agentic tools management by meta tool | |
|
||||
| MCP | Support streamable HTTP/SSE/StdIO transport | [MCP](https://doc.agentscope.io/tutorial/task_mcp.html) |
|
||||
| | Support both **stateful** and **stateless** mode MCP Client | |
|
||||
| | Support client- & function-level fine-grained control | |
|
||||
| agent | Support async execution | |
|
||||
| | Support parallel tool calls | |
|
||||
| | Support realtime steering interruption and customized handling | |
|
||||
| | Support automatic state management | |
|
||||
| | Support agent-controlled long-term memory | |
|
||||
| | Support agent hooks | |
|
||||
| tracing | Support OpenTelemetry-based tracing in LLM, tools, agent and formatter | [Tracing](https://doc.agentscope.io/tutorial/task_tracing.html) |
|
||||
| | Support connecting to third-party tracing platforms (e.g. Arize-Phoenix, Langfuse) | |
|
||||
| memory | Support long-term memory | [Memory](https://doc.agentscope.io/tutorial/task_long_term_memory.html) |
|
||||
| session | Provide session/application-level automatic state management | [Session](https://doc.agentscope.io/tutorial/task_state.html) |
|
||||
| evaluation | Provide distributed and parallel evaluation | [Evaluation](https://doc.agentscope.io/tutorial/task_eval.html) |
|
||||
| formatter | Support multi-agent prompt formatting with tools API | [Prompt Formatter](https://doc.agentscope.io/tutorial/task_prompt.html) |
|
||||
| | Support truncation-based formatter strategy | |
|
||||
| plan | Support ReAct-based long-term planning | [Plan](https://doc.agentscope.io/tutorial/task_plan.html) |
|
||||
| | Support manual plan specification | |
|
||||
| RAG | Support agentic RAG | [RAG](https://doc.agentscope.io/tutorial/task_rag.html) |
|
||||
| | Support multimodal RAG | |
|
||||
| ... | | |
|
||||
|
||||
## 📢 News
|
||||
- **[2025-11]** [Contributing Guide](./CONTRIBUTING.md) is online now! Welcome to contribute to AgentScope.
|
||||
- **[2025-09]** **RAG** module in AgentScope 1.0 is online now! Check our [tutorial](https://doc.agentscope.io/tutorial/task_rag.html) and [example](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/rag) for more details.
|
||||
- **[2025-09]** **Voice agent** is online! `ReActAgent` supports Qwen-Omni and GPT-Audio natively now, check our [new example](https://github.com/agentscope-ai/agentscope/tree/main/examples/agent/voice_agent) and [roadmap](https://github.com/agentscope-ai/agentscope/issues/773).
|
||||
- **[2025-09]** A new powerful 📋**Plan** module is online now! Check out the [tutorial](https://doc.agentscope.io/tutorial/task_plan.html) for more details.
|
||||
- **[2025-09]** **AgentScope Runtime** is open-sourced now! Enabling effective agent deployment with sandboxed tool execution for production-ready AI applications. Check out the [GitHub repo](https://github.com/agentscope-ai/agentscope-runtime).
|
||||
- **[2025-09]** **AgentScope Studio** is open-sourced now! Check out the [GitHub repo](https://github.com/agentscope-ai/agentscope-studio).
|
||||
- **[2025-08]** The new tutorial of v1 is online now! Check out the [tutorial](https://doc.agentscope.io) for more details.
|
||||
- **[2025-08]** 🎉🎉 AgentScope v1 is released now! This version fully embraces the asynchronous execution, providing many new features and improvements. Check out [changelog](https://github.com/agentscope-ai/agentscope/blob/main/docs/changelog.md) for detailed changes.
|
||||
|
||||
## 💬 Contact
|
||||
|
||||
Welcome to join our community on
|
||||
|
||||
| [Discord](https://discord.gg/eYMpfnkG8h) | DingTalk |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
|
||||
| <img src="https://gw.alicdn.com/imgextra/i1/O1CN01hhD1mu1Dd3BWVUvxN_!!6000000000238-2-tps-400-400.png" width="100" height="100"> | <img src="https://img.alicdn.com/imgextra/i1/O1CN01LxzZha1thpIN2cc2E_!!6000000005934-2-tps-497-477.png" width="100" height="100"> |
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
## 📑 Table of Contents
|
||||
|
||||
- [🚀 Quickstart](#-quickstart)
|
||||
- [💻 Installation](#-installation)
|
||||
- [🛠️ From source](#-from-source)
|
||||
- [🔄 Using uv (recommended for faster installs)](#-using-uv-recommended-for-faster-installs)
|
||||
- [📦 From PyPi](#-from-pypi)
|
||||
- [📝 Example](#-example)
|
||||
- [👋 Hello AgentScope!](#-hello-agentscope)
|
||||
- [🎯 Realtime Steering](#-realtime-steering)
|
||||
- [🛠️ Fine-Grained MCP Control](#-fine-grained-mcp-control)
|
||||
- [🧑🤝🧑 Multi-Agent Conversation](#-multi-agent-conversation)
|
||||
- [💻 AgentScope Studio](#-agentscope-studio)
|
||||
- [📖 Documentation](#-documentation)
|
||||
- [🤝 Contributing](#-contributing)
|
||||
- [⚖️ License](#-license)
|
||||
- [📚 Publications](#-publications)
|
||||
- [✨ Contributors](#-contributors)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
## 🚀 Quickstart
|
||||
|
||||
### 💻 Installation
|
||||
|
||||
> AgentScope requires **Python 3.10** or higher.
|
||||
|
||||
#### 🛠️ From source
|
||||
|
||||
```bash
|
||||
# Pull the source code from GitHub
|
||||
git clone -b main https://github.com/agentscope-ai/agentscope.git
|
||||
|
||||
# Install the package in editable mode
|
||||
cd agentscope
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
#### 🔄 Using uv (recommended for faster installs)
|
||||
|
||||
[uv](https://github.com/astral-sh/uv) is a fast Python package installer and resolver, written in Rust.
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone -b main https://github.com/agentscope-ai/agentscope.git
|
||||
cd agentscope
|
||||
|
||||
# Install with uv
|
||||
uv pip install -e .
|
||||
```
|
||||
|
||||
#### 📦 From PyPi
|
||||
|
||||
```bash
|
||||
pip install agentscope
|
||||
```
|
||||
|
||||
Or with uv:
|
||||
|
||||
```bash
|
||||
uv pip install agentscope
|
||||
```
|
||||
|
||||
## 📝 Example
|
||||
|
||||
### 👋 Hello AgentScope!
|
||||
|
||||
Start with a conversation between user and a ReAct agent 🤖 named "Friday"!
|
||||
|
||||
```python
|
||||
from agentscope.agent import ReActAgent, UserAgent
|
||||
from agentscope.model import DashScopeChatModel
|
||||
from agentscope.formatter import DashScopeChatFormatter
|
||||
from agentscope.memory import InMemoryMemory
|
||||
from agentscope.tool import Toolkit, execute_python_code, execute_shell_command
|
||||
import os, asyncio
|
||||
|
||||
|
||||
async def main():
|
||||
toolkit = Toolkit()
|
||||
toolkit.register_tool_function(execute_python_code)
|
||||
toolkit.register_tool_function(execute_shell_command)
|
||||
|
||||
agent = ReActAgent(
|
||||
name="Friday",
|
||||
sys_prompt="You're a helpful assistant named Friday.",
|
||||
model=DashScopeChatModel(
|
||||
model_name="qwen-max",
|
||||
api_key=os.environ["DASHSCOPE_API_KEY"],
|
||||
stream=True,
|
||||
),
|
||||
memory=InMemoryMemory(),
|
||||
formatter=DashScopeChatFormatter(),
|
||||
toolkit=toolkit,
|
||||
)
|
||||
|
||||
user = UserAgent(name="user")
|
||||
|
||||
msg = None
|
||||
while True:
|
||||
msg = await agent(msg)
|
||||
msg = await user(msg)
|
||||
if msg.get_text_content() == "exit":
|
||||
break
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
### 🎯 Realtime Steering
|
||||
|
||||
Natively support **realtime interruption** in ``ReActAgent`` with robust memory preservation, and convert interruption into an **observable event** for agent to seamlessly resume conversations.
|
||||
|
||||
<p align="center">
|
||||
<img src="./assets/images/realtime_steering_zh.gif" alt="Realtime Steering" width="49%"/>
|
||||
<img src="./assets/images/realtime_steering_en.gif" alt="Realtime Steering" width="49%"/>
|
||||
</p>
|
||||
|
||||
### 🛠️ Fine-Grained MCP Control
|
||||
|
||||
Developers can obtain the MCP tool as a **local callable function**, and use it anywhere (e.g. call directly, pass to agent, wrap into a more complex tool, etc.)
|
||||
|
||||
```python
|
||||
from agentscope.mcp import HttpStatelessClient
|
||||
from agentscope.tool import Toolkit
|
||||
import os
|
||||
|
||||
async def fine_grained_mcp_control():
|
||||
# Initialize the MCP client
|
||||
client = HttpStatelessClient(
|
||||
name="gaode_mcp",
|
||||
transport="streamable_http",
|
||||
url=f"https://mcp.amap.com/mcp?key={os.environ['GAODE_API_KEY']}",
|
||||
)
|
||||
|
||||
# Obtain the MCP tool as a **local callable function**, and use it anywhere
|
||||
func = await client.get_callable_function(func_name="maps_geo")
|
||||
|
||||
# Option 1: Call directly
|
||||
await func(address="Tiananmen Square", city="Beijing")
|
||||
|
||||
# Option 2: Pass to agent as a tool
|
||||
toolkit = Toolkit()
|
||||
toolkit.register_tool_function(func)
|
||||
# ...
|
||||
|
||||
# Option 3: Wrap into a more complex tool
|
||||
# ...
|
||||
```
|
||||
|
||||
### 🧑🤝🧑 Multi-Agent Conversation
|
||||
|
||||
AgentScope provides ``MsgHub`` and pipelines to streamline multi-agent conversations, offering efficient message routing and seamless information sharing
|
||||
|
||||
```python
|
||||
from agentscope.pipeline import MsgHub, sequential_pipeline
|
||||
from agentscope.message import Msg
|
||||
import asyncio
|
||||
|
||||
async def multi_agent_conversation():
|
||||
# Create agents
|
||||
agent1 = ...
|
||||
agent2 = ...
|
||||
agent3 = ...
|
||||
agent4 = ...
|
||||
|
||||
# Create a message hub to manage multi-agent conversation
|
||||
async with MsgHub(
|
||||
participants=[agent1, agent2, agent3],
|
||||
announcement=Msg("Host", "Introduce yourselves.", "assistant")
|
||||
) as hub:
|
||||
# Speak in a sequential manner
|
||||
await sequential_pipeline([agent1, agent2, agent3])
|
||||
# Dynamic manage the participants
|
||||
hub.add(agent4)
|
||||
hub.delete(agent3)
|
||||
await hub.broadcast(Msg("Host", "Goodbye!", "assistant"))
|
||||
|
||||
asyncio.run(multi_agent_conversation())
|
||||
```
|
||||
|
||||
### 💻 AgentScope Studio
|
||||
|
||||
Use the following command to install and start AgentScope Studio, to trace and visualize your agent application.
|
||||
|
||||
```bash
|
||||
npm install -g @agentscope/studio
|
||||
|
||||
as_studio
|
||||
```
|
||||
|
||||
<p align="center">
|
||||
<img
|
||||
src="./assets/images/home.gif"
|
||||
width="49%"
|
||||
alt="home"
|
||||
/>
|
||||
<img
|
||||
src="./assets/images/projects.gif"
|
||||
width="49%"
|
||||
alt="projects"
|
||||
/>
|
||||
<img
|
||||
src="./assets/images/runtime.gif"
|
||||
width="49%"
|
||||
alt="runtime"
|
||||
/>
|
||||
<img
|
||||
src="./assets/images/friday.gif"
|
||||
width="49%"
|
||||
alt="friday"
|
||||
/>
|
||||
</p>
|
||||
|
||||
|
||||
## 📖 Documentation
|
||||
|
||||
- Tutorial
|
||||
- [Installation](https://doc.agentscope.io/tutorial/quickstart_installation.html)
|
||||
- [Key Concepts](https://doc.agentscope.io/tutorial/quickstart_key_concept.html)
|
||||
- [Create Message](https://doc.agentscope.io/tutorial/quickstart_message.html)
|
||||
- [ReAct Agent](https://doc.agentscope.io/tutorial/quickstart_agent.html)
|
||||
- Workflow
|
||||
- [Conversation](https://doc.agentscope.io/tutorial/workflow_conversation.html)
|
||||
- [Multi-Agent Debate](https://doc.agentscope.io/tutorial/workflow_multiagent_debate.html)
|
||||
- [Concurrent Agents](https://doc.agentscope.io/tutorial/workflow_concurrent_agents.html)
|
||||
- [Routing](https://doc.agentscope.io/tutorial/workflow_routing.html)
|
||||
- [Handoffs](https://doc.agentscope.io/tutorial/workflow_handoffs.html)
|
||||
- FAQ
|
||||
- [FAQ](https://doc.agentscope.io/tutorial/faq.html)
|
||||
- Task Guides
|
||||
- [Model](https://doc.agentscope.io/tutorial/task_model.html)
|
||||
- [Prompt Formatter](https://doc.agentscope.io/tutorial/task_prompt.html)
|
||||
- [Tool](https://doc.agentscope.io/tutorial/task_tool.html)
|
||||
- [Memory](https://doc.agentscope.io/tutorial/task_memory.html)
|
||||
- [Long-Term Memory](https://doc.agentscope.io/tutorial/task_long_term_memory.html)
|
||||
- [Agent](https://doc.agentscope.io/tutorial/task_agent.html)
|
||||
- [Pipeline](https://doc.agentscope.io/tutorial/task_pipeline.html)
|
||||
- [Plan](https://doc.agentscope.io/tutorial/task_plan.html)
|
||||
- [State/Session Management](https://doc.agentscope.io/tutorial/task_state.html)
|
||||
- [Agent Hooks](https://doc.agentscope.io/tutorial/task_hook.html)
|
||||
- [MCP](https://doc.agentscope.io/tutorial/task_mcp.html)
|
||||
- [AgentScope Studio](https://doc.agentscope.io/tutorial/task_studio.html)
|
||||
- [Tracing](https://doc.agentscope.io/tutorial/task_tracing.html)
|
||||
- [Evaluation](https://doc.agentscope.io/tutorial/task_eval.html)
|
||||
- [Embedding](https://doc.agentscope.io/tutorial/task_embedding.html)
|
||||
- [Token](https://doc.agentscope.io/tutorial/task_token.html)
|
||||
- API
|
||||
- [API Docs](https://doc.agentscope.io/api/agentscope.html)
|
||||
- [Examples](https://github.com/agentscope-ai/agentscope/tree/main/examples)
|
||||
- Functionality
|
||||
- [MCP](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/mcp)
|
||||
- [Plan](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/plan)
|
||||
- [Structured Output](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/structured_output)
|
||||
- [RAG](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/rag)
|
||||
- [Long-Term Memory](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/long_term_memory)
|
||||
- [Session with SQLite](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/session_with_sqlite)
|
||||
- [Stream Printing Messages](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/stream_printing_messages)
|
||||
- Agent
|
||||
- [ReAct Agent](https://github.com/agentscope-ai/agentscope/tree/main/examples/agent/react_agent)
|
||||
- [Voice Agent](https://github.com/agentscope-ai/agentscope/tree/main/examples/agent/voice_agent)
|
||||
- [Deep Research Agent](https://github.com/agentscope-ai/agentscope/tree/main/examples/agent/deep_research_agent)
|
||||
- [Browser-use Agent](https://github.com/agentscope-ai/agentscope/tree/main/examples/agent/browser_agent)
|
||||
- [Meta Planner Agent](https://github.com/agentscope-ai/agentscope/tree/main/examples/agent/meta_planner_agent)
|
||||
- Game
|
||||
- [Nine-player Werewolves](https://github.com/agentscope-ai/agentscope/tree/main/examples/game/werewolves)
|
||||
- Workflow
|
||||
- [Multi-agent Debate](https://github.com/agentscope-ai/agentscope/tree/main/examples/workflows/multiagent_debate)
|
||||
- [Multi-agent Conversation](https://github.com/agentscope-ai/agentscope/tree/main/examples/workflows/multiagent_conversation)
|
||||
- [Multi-agent Concurrent](https://github.com/agentscope-ai/agentscope/tree/main/examples/workflows/multiagent_concurrent)
|
||||
- Evaluation
|
||||
- [ACEBench](https://github.com/agentscope-ai/agentscope/tree/main/examples/evaluation/ace_bench)
|
||||
- Training
|
||||
- [Reinforcement learning (RL) with Trinity-RFT](https://github.com/agentscope-ai/agentscope/tree/main/examples/training/react_agent)
|
||||
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
We welcome contributions from the community! Please refer to our [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines
|
||||
on how to contribute.
|
||||
|
||||
## ⚖️ License
|
||||
|
||||
AgentScope is released under Apache License 2.0.
|
||||
|
||||
## 📚 Publications
|
||||
|
||||
If you find our work helpful for your research or application, please cite our papers.
|
||||
|
||||
- [AgentScope 1.0: A Developer-Centric Framework for Building Agentic Applications](https://arxiv.org/abs/2508.16279)
|
||||
|
||||
- [AgentScope: A Flexible yet Robust Multi-Agent Platform](https://arxiv.org/abs/2402.14034)
|
||||
|
||||
```
|
||||
@article{agentscope_v1,
|
||||
author = {
|
||||
Dawei Gao,
|
||||
Zitao Li,
|
||||
Yuexiang Xie,
|
||||
Weirui Kuang,
|
||||
Liuyi Yao,
|
||||
Bingchen Qian,
|
||||
Zhijian Ma,
|
||||
Yue Cui,
|
||||
Haohao Luo,
|
||||
Shen Li,
|
||||
Lu Yi,
|
||||
Yi Yu,
|
||||
Shiqi He,
|
||||
Zhiling Luo,
|
||||
Wenmeng Zhou,
|
||||
Zhicheng Zhang,
|
||||
Xuguang He,
|
||||
Ziqian Chen,
|
||||
Weikai Liao,
|
||||
Farruh Isakulovich Kushnazarov,
|
||||
Yaliang Li,
|
||||
Bolin Ding,
|
||||
Jingren Zhou}
|
||||
title = {AgentScope 1.0: A Developer-Centric Framework for Building Agentic Applications},
|
||||
journal = {CoRR},
|
||||
volume = {abs/2508.16279},
|
||||
year = {2025},
|
||||
}
|
||||
|
||||
@article{agentscope,
|
||||
author = {
|
||||
Dawei Gao,
|
||||
Zitao Li,
|
||||
Xuchen Pan,
|
||||
Weirui Kuang,
|
||||
Zhijian Ma,
|
||||
Bingchen Qian,
|
||||
Fei Wei,
|
||||
Wenhao Zhang,
|
||||
Yuexiang Xie,
|
||||
Daoyuan Chen,
|
||||
Liuyi Yao,
|
||||
Hongyi Peng,
|
||||
Zeyu Zhang,
|
||||
Lin Zhu,
|
||||
Chen Cheng,
|
||||
Hongzhu Shi,
|
||||
Yaliang Li,
|
||||
Bolin Ding,
|
||||
Jingren Zhou}
|
||||
title = {AgentScope: A Flexible yet Robust Multi-Agent Platform},
|
||||
journal = {CoRR},
|
||||
volume = {abs/2402.14034},
|
||||
year = {2024},
|
||||
}
|
||||
```
|
||||
|
||||
## ✨ Contributors
|
||||
|
||||
All thanks to our contributors:
|
||||
|
||||
<a href="https://github.com/agentscope-ai/agentscope/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=agentscope-ai/agentscope&max=999&columns=12&anon=1" />
|
||||
</a>
|
||||
@@ -0,0 +1,315 @@
|
||||
agentscope-1.0.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
agentscope-1.0.7.dist-info/METADATA,sha256=HD2a1imJIVJ1oFh55nhcZTP0Li5q-9o1ZDg-K73SVh8,25920
|
||||
agentscope-1.0.7.dist-info/RECORD,,
|
||||
agentscope-1.0.7.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
agentscope-1.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
||||
agentscope-1.0.7.dist-info/licenses/LICENSE,sha256=QYa8rfNYxgCABgMJdp22sqNScg1zU9gnu1dMYA_umRM,20637
|
||||
agentscope-1.0.7.dist-info/top_level.txt,sha256=uYSDqkiAOqFFfMz9DGnkhn0_nNVwo1uaFYZQikHbWNM,11
|
||||
agentscope/__init__.py,sha256=MkP1MQ4hMFmRQF8qeUUVuBcCGvLS4fa-eqvogl8aj84,3220
|
||||
agentscope/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/__pycache__/_config.cpython-313.pyc,,
|
||||
agentscope/__pycache__/_logging.cpython-313.pyc,,
|
||||
agentscope/__pycache__/_version.cpython-313.pyc,,
|
||||
agentscope/_config.py,sha256=W1Y2lQbTXj1esxwm_sK2yFqztacz-L1OzRJsaei04GM,767
|
||||
agentscope/_logging.py,sha256=XzcUTb7MfRZkc-B3N1IV-jpHaZG0yFirZyfuGa7HOA4,1223
|
||||
agentscope/_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
agentscope/_utils/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/_utils/__pycache__/_common.cpython-313.pyc,,
|
||||
agentscope/_utils/__pycache__/_mixin.cpython-313.pyc,,
|
||||
agentscope/_utils/_common.py,sha256=ghJITFirhNAwTl_ifi9cI6Oc_Fsvlimiv_sxwi4JXZE,8169
|
||||
agentscope/_utils/_mixin.py,sha256=9co2GJyiShSq6HiQ1KwGABr3mfYw2tyvlzCMgI8L0-w,219
|
||||
agentscope/_version.py,sha256=KpA_lRRXOAnkM0n8CqdbV0FanoevNyEft5-YZ-i1-wI,80
|
||||
agentscope/agent/__init__.py,sha256=fxBL1RmxC__kHPRVYkEj03EJ1mYO32vKsbY5wDIV_x8,496
|
||||
agentscope/agent/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/agent/__pycache__/_agent_base.cpython-313.pyc,,
|
||||
agentscope/agent/__pycache__/_agent_meta.cpython-313.pyc,,
|
||||
agentscope/agent/__pycache__/_react_agent.cpython-313.pyc,,
|
||||
agentscope/agent/__pycache__/_react_agent_base.cpython-313.pyc,,
|
||||
agentscope/agent/__pycache__/_user_agent.cpython-313.pyc,,
|
||||
agentscope/agent/__pycache__/_user_input.cpython-313.pyc,,
|
||||
agentscope/agent/_agent_base.py,sha256=gxF0tuQN0XebkWR-uVM-a_RTR6eKoJnJOvJT90UegKI,24299
|
||||
agentscope/agent/_agent_meta.py,sha256=Ilda4Fonq29oeQ3kUDTIs8db655MQqWIhzvxGiGUrSw,5730
|
||||
agentscope/agent/_react_agent.py,sha256=zQKd9L19k3hjJmCRZYp2GjqedHh5-A45k-8xWcGSDoI,28676
|
||||
agentscope/agent/_react_agent_base.py,sha256=haWRx93D7A_zmhVVJLlJ_YD8I2pCM7g77vok761DOug,3707
|
||||
agentscope/agent/_user_agent.py,sha256=50kYNXWSfYE7L0x8D1Vmzsl1-mg20nSaCDYROzEusPI,4219
|
||||
agentscope/agent/_user_input.py,sha256=oXtHQ8XapV0ov_8S40MAt2EWDHmvC-_zAEZsR9lUt8g,13105
|
||||
agentscope/embedding/__init__.py,sha256=aiGzcY4qzX7a-ieseIH86_8zhry5yaII5Wdkg-hKjXY,871
|
||||
agentscope/embedding/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/embedding/__pycache__/_cache_base.cpython-313.pyc,,
|
||||
agentscope/embedding/__pycache__/_dashscope_embedding.cpython-313.pyc,,
|
||||
agentscope/embedding/__pycache__/_dashscope_multimodal_embedding.cpython-313.pyc,,
|
||||
agentscope/embedding/__pycache__/_embedding_base.cpython-313.pyc,,
|
||||
agentscope/embedding/__pycache__/_embedding_response.cpython-313.pyc,,
|
||||
agentscope/embedding/__pycache__/_embedding_usage.cpython-313.pyc,,
|
||||
agentscope/embedding/__pycache__/_file_cache.cpython-313.pyc,,
|
||||
agentscope/embedding/__pycache__/_gemini_embedding.cpython-313.pyc,,
|
||||
agentscope/embedding/__pycache__/_ollama_embedding.cpython-313.pyc,,
|
||||
agentscope/embedding/__pycache__/_openai_embedding.cpython-313.pyc,,
|
||||
agentscope/embedding/_cache_base.py,sha256=QV_D9Q1Rbtts1BporJVomFwaLyG6nsy9GxhLQNxh4lY,1800
|
||||
agentscope/embedding/_dashscope_embedding.py,sha256=r0qbxhs1kfNgPkgWIvcPXKDdKfVFhKKERpqW9DyfRtM,5905
|
||||
agentscope/embedding/_dashscope_multimodal_embedding.py,sha256=XQ3Dx7sXC18fTXW6kkudhMwJKqiVSfrPOJrGeYpXFEg,8682
|
||||
agentscope/embedding/_embedding_base.py,sha256=sgt_GsFGiuzSCt1-gzhLKJ3Cn4usYbGfHqliHIWMZg8,1191
|
||||
agentscope/embedding/_embedding_response.py,sha256=naEqlewn6J5UyteBewwknH6HlZVTo2SRhN714JhOk2U,1093
|
||||
agentscope/embedding/_embedding_usage.py,sha256=Z1q5yPXuGR8BpB7yUxcn-vPfmRP7gqnGmBjsSGC2f1w,579
|
||||
agentscope/embedding/_file_cache.py,sha256=2MZpiurcVgqkCTIq2U_8Z0n_D0I1Z87owXY0K-Fqfvk,7126
|
||||
agentscope/embedding/_gemini_embedding.py,sha256=5WgGi9iJK6OSbCO_2mG_JbgSxUotR44grNo9CF6yaL0,3549
|
||||
agentscope/embedding/_ollama_embedding.py,sha256=XRAicJgcD8DDHHy0W5du_Jsio4JC3L6pqvctexUOFKA,3379
|
||||
agentscope/embedding/_openai_embedding.py,sha256=ZWcyLR_a9DuekdmHkxD93ck6Hk3ZmytNsLYognCFacE,3491
|
||||
agentscope/evaluate/__init__.py,sha256=8FWPPEnQh95u9TxN8Forj8-b-in2a4_yxn_5F-yMeV8,861
|
||||
agentscope/evaluate/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/evaluate/__pycache__/_benchmark_base.cpython-313.pyc,,
|
||||
agentscope/evaluate/__pycache__/_metric_base.cpython-313.pyc,,
|
||||
agentscope/evaluate/__pycache__/_solution.cpython-313.pyc,,
|
||||
agentscope/evaluate/__pycache__/_task.cpython-313.pyc,,
|
||||
agentscope/evaluate/_ace_benchmark/__init__.py,sha256=ZtgAiBvYaSJOmUPXX2P5hf_cJdECxJiMgEtyt99pI38,331
|
||||
agentscope/evaluate/_ace_benchmark/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/evaluate/_ace_benchmark/__pycache__/_ace_benchmark.cpython-313.pyc,,
|
||||
agentscope/evaluate/_ace_benchmark/__pycache__/_ace_metric.cpython-313.pyc,,
|
||||
agentscope/evaluate/_ace_benchmark/__pycache__/_ace_tools_zh.cpython-313.pyc,,
|
||||
agentscope/evaluate/_ace_benchmark/_ace_benchmark.py,sha256=8MV9V0FMSV3YfymVKd_ybJRt_dzybKBTJMeivZ393FI,8151
|
||||
agentscope/evaluate/_ace_benchmark/_ace_metric.py,sha256=6_VBBJ50v7aL6OdwJXRRUrqx2gdWtnpM6jlcZMHP6cQ,4225
|
||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__init__.py,sha256=DFWSvwmPolmgqEbqwmkvO05mTr2QNoneO_eXFjEw7ac,327
|
||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__pycache__/_food_platform_api.cpython-313.pyc,,
|
||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__pycache__/_message_api.cpython-313.pyc,,
|
||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__pycache__/_reminder_api.cpython-313.pyc,,
|
||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__pycache__/_shared_state.cpython-313.pyc,,
|
||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__pycache__/_travel_api.cpython-313.pyc,,
|
||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/_food_platform_api.py,sha256=TUQD6gR2VzjtUDK9pZKoWr-H9U0opKcUjvqRmP3q58c,9871
|
||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/_message_api.py,sha256=oJcSfj5Kw_BIMI3eC3LsxB5ZI_nN4o_wd0jOX6OXPGA,11784
|
||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/_reminder_api.py,sha256=ObmgAI4UnpoZmgiRpGvqwXL2Bs5YH1KQG1JVBM9AXmM,7082
|
||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/_shared_state.py,sha256=sLkWasNv57-YxeMEj-GIj6mB6LN0RmsIpOaL3fjImmg,551
|
||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/_travel_api.py,sha256=aa5ixysqx6mO3Msueyv_vrJ3yJbdMBKkBmyaKoozJoU,28644
|
||||
agentscope/evaluate/_ace_benchmark/_ace_tools_zh.py,sha256=f10Vu8N82BYe5aBVo8hi2FkC1f0VKMqrNouWEG8DsQM,4052
|
||||
agentscope/evaluate/_benchmark_base.py,sha256=YqFeDn6G-e8njE48Yso5-tRSeE5dZzDRhwvJKCnriQQ,1263
|
||||
agentscope/evaluate/_evaluator/__init__.py,sha256=2g3K8cHhugTwf64ywiF-yLFihpvlrBMX01bUNTQ-yik,280
|
||||
agentscope/evaluate/_evaluator/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/evaluate/_evaluator/__pycache__/_evaluator_base.cpython-313.pyc,,
|
||||
agentscope/evaluate/_evaluator/__pycache__/_general_evaluator.cpython-313.pyc,,
|
||||
agentscope/evaluate/_evaluator/__pycache__/_ray_evaluator.cpython-313.pyc,,
|
||||
agentscope/evaluate/_evaluator/_evaluator_base.py,sha256=Y7LWZDTLmKyiq4WvpLj6dSMJSZw4N80ty-BFEAg5Wxg,7317
|
||||
agentscope/evaluate/_evaluator/_general_evaluator.py,sha256=GSMdijP5a8KPVvc6QrAqOI7pRFyXhd-n3yKekgqSHB0,3817
|
||||
agentscope/evaluate/_evaluator/_ray_evaluator.py,sha256=CS_Hng_j2lY5nlaN5Fb1Uq5hL99dcNyzu2OaGl_HLk0,6075
|
||||
agentscope/evaluate/_evaluator_storage/__init__.py,sha256=bSdhxI83A-2OVMX6L-ZO8EwYytyBQy6XwGIFQbdTod4,262
|
||||
agentscope/evaluate/_evaluator_storage/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/evaluate/_evaluator_storage/__pycache__/_evaluator_storage_base.cpython-313.pyc,,
|
||||
agentscope/evaluate/_evaluator_storage/__pycache__/_file_evaluator_storage.cpython-313.pyc,,
|
||||
agentscope/evaluate/_evaluator_storage/_evaluator_storage_base.py,sha256=IW4A6WkBGf43uGj59f7Eu5ySTiX1rmPbpjX1iYjCl8A,5459
|
||||
agentscope/evaluate/_evaluator_storage/_file_evaluator_storage.py,sha256=xPBZ6GXCSL3YMJJNsqH0-bzCxo4_FhZDEqLJcGXLexA,11096
|
||||
agentscope/evaluate/_metric_base.py,sha256=ksYBDhjmE8vTv8cMy31HBhbvkGgIYhUBiC8Qw4zpOAE,2663
|
||||
agentscope/evaluate/_solution.py,sha256=CDbGtYOerCd_o2WgKMnFUPrzF51tXeAcMRu2-poyyho,1194
|
||||
agentscope/evaluate/_task.py,sha256=RJw6GbBTZmYN7bZY3DR6qEDKB4bgV3zwNbWt5vZZEhU,1585
|
||||
agentscope/exception/__init__.py,sha256=eaWWszusA4Lm3CaPmyZCpLBkjwxc17IAPq0MioznbQQ,361
|
||||
agentscope/exception/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/exception/__pycache__/_exception_base.cpython-313.pyc,,
|
||||
agentscope/exception/__pycache__/_tool.cpython-313.pyc,,
|
||||
agentscope/exception/_exception_base.py,sha256=o0VAg5seb9GnJNs_eZMrlmxqbI7UEyzwr7B1gwA48oQ,660
|
||||
agentscope/exception/_tool.py,sha256=AsCWmwM7HF5fFKD6JhI6ohRGMZG7i8H1cwWj3xfiPUc,512
|
||||
agentscope/formatter/__init__.py,sha256=mgg0ZCZsk-beTELeVU9HVaU9T38w3u5gMyA4LT-wwag,1184
|
||||
agentscope/formatter/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/formatter/__pycache__/_anthropic_formatter.cpython-313.pyc,,
|
||||
agentscope/formatter/__pycache__/_dashscope_formatter.cpython-313.pyc,,
|
||||
agentscope/formatter/__pycache__/_deepseek_formatter.cpython-313.pyc,,
|
||||
agentscope/formatter/__pycache__/_formatter_base.cpython-313.pyc,,
|
||||
agentscope/formatter/__pycache__/_gemini_formatter.cpython-313.pyc,,
|
||||
agentscope/formatter/__pycache__/_ollama_formatter.cpython-313.pyc,,
|
||||
agentscope/formatter/__pycache__/_openai_formatter.cpython-313.pyc,,
|
||||
agentscope/formatter/__pycache__/_truncated_formatter_base.cpython-313.pyc,,
|
||||
agentscope/formatter/_anthropic_formatter.py,sha256=yJMg6IZX538aKmC6JqYzddhVeLSGz92X9ubjg9MNvaA,8226
|
||||
agentscope/formatter/_dashscope_formatter.py,sha256=FWkX2_zHXCaq4sK_o6NH5b_qcXin_tODDhFqAk0x78A,14548
|
||||
agentscope/formatter/_deepseek_formatter.py,sha256=5Ewi8c99qYL5ZCyE6oKek1x3cqNMfHDtXay43Goohi0,8143
|
||||
agentscope/formatter/_formatter_base.py,sha256=FQKf_3KrydfzuAIL5m5YbC36pfz7lXjnnjG_VI25Cm0,3690
|
||||
agentscope/formatter/_gemini_formatter.py,sha256=n6okME8L623zoLayNXG1uf-UEDgB3xydmpuWipUm4kY,13036
|
||||
agentscope/formatter/_ollama_formatter.py,sha256=fqGKIdhPyMizYSBLj-YwtcbIPBriXolEvrPQuR-ZeiY,10290
|
||||
agentscope/formatter/_openai_formatter.py,sha256=6wrcmO7mqba1X-VWMbYEGjWIv7NfhW-4nctLqvuDaU0,13214
|
||||
agentscope/formatter/_truncated_formatter_base.py,sha256=xKqBL-qiDZSLaHq1ls9fUZZY8xSikdpLqC85hVSWbDM,10211
|
||||
agentscope/hooks/__init__.py,sha256=gn0gD6IUtvlN8fGSy9YZRcS3ANpewvyPjQZuHo2SylU,670
|
||||
agentscope/hooks/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/hooks/__pycache__/_studio_hooks.cpython-313.pyc,,
|
||||
agentscope/hooks/_studio_hooks.py,sha256=fxGjYIwqQ1vs0Yr3zrcfAwO1ZWLyoSvG_0MCmjLnBog,1143
|
||||
agentscope/mcp/__init__.py,sha256=8_x7Loaxt1PVh5h5ubr_RdnyF9wRJOhSsBYMHWaPFRw,587
|
||||
agentscope/mcp/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/mcp/__pycache__/_client_base.cpython-313.pyc,,
|
||||
agentscope/mcp/__pycache__/_http_stateful_client.cpython-313.pyc,,
|
||||
agentscope/mcp/__pycache__/_http_stateless_client.cpython-313.pyc,,
|
||||
agentscope/mcp/__pycache__/_mcp_function.cpython-313.pyc,,
|
||||
agentscope/mcp/__pycache__/_stateful_client_base.cpython-313.pyc,,
|
||||
agentscope/mcp/__pycache__/_stdio_stateful_client.cpython-313.pyc,,
|
||||
agentscope/mcp/_client_base.py,sha256=XzYjrxwSzIEbAVO5IzUlbKTtzdr41fTfBtSUnISpGvY,3274
|
||||
agentscope/mcp/_http_stateful_client.py,sha256=Ekwd1KUJ2RX9oWvv3ZEqDy1FQaXa-hZbSp019K_eR_M,3186
|
||||
agentscope/mcp/_http_stateless_client.py,sha256=LotK9FgzXtSi7VSSGxF0PwYagARBd72P2derYe2Itmg,5223
|
||||
agentscope/mcp/_mcp_function.py,sha256=b_bK9chwTriE7pbncuzG3j46HZkG8BSugvpBr8Z90bI,2604
|
||||
agentscope/mcp/_stateful_client_base.py,sha256=l01VBdAsPNtwR50TnJtwx7NqcIB89V6xpiSN-QUFBeU,5206
|
||||
agentscope/mcp/_stdio_stateful_client.py,sha256=IjDjvha_82RCJgQ8eOitQfPnBVdWzy-ljzzYxnpAgvo,2950
|
||||
agentscope/memory/__init__.py,sha256=PlElb2Rt9lL9JcNZ6ADCvCJwaMPlhPdZIaaBkUlOHfs,555
|
||||
agentscope/memory/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/memory/__pycache__/_in_memory_memory.cpython-313.pyc,,
|
||||
agentscope/memory/__pycache__/_long_term_memory_base.cpython-313.pyc,,
|
||||
agentscope/memory/__pycache__/_mem0_long_term_memory.cpython-313.pyc,,
|
||||
agentscope/memory/__pycache__/_mem0_utils.cpython-313.pyc,,
|
||||
agentscope/memory/__pycache__/_memory_base.cpython-313.pyc,,
|
||||
agentscope/memory/_in_memory_memory.py,sha256=wEpxEqJ0rKui4AVrPz4Bs7JYLc4FmZmp6brUxm9U9nw,3694
|
||||
agentscope/memory/_long_term_memory_base.py,sha256=PQj1W7cLZVyO6gEbaqCeJm_uGG4oa6kRb_3PNgtwbBA,2976
|
||||
agentscope/memory/_mem0_long_term_memory.py,sha256=UsETvCSdwdaP59CphU5SB_BmOvCUHVkmDdFd0POFScs,21243
|
||||
agentscope/memory/_mem0_utils.py,sha256=9cKMy6KUKfAT5CF5oaIrJp90-qFaOZRMbLVg1VZvyMA,7617
|
||||
agentscope/memory/_memory_base.py,sha256=HcM23pIsXULYX6lT1DsGODG72ZWo3EA2TE6kbJEXQG4,1218
|
||||
agentscope/memory/_reme/__init__.py,sha256=mIuY8wRbVVYrQk_S05RBLivY0cnWDfq7Ere-oASf0G0,364
|
||||
agentscope/memory/_reme/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/memory/_reme/__pycache__/_reme_long_term_memory_base.cpython-313.pyc,,
|
||||
agentscope/memory/_reme/__pycache__/_reme_personal_long_term_memory.cpython-313.pyc,,
|
||||
agentscope/memory/_reme/__pycache__/_reme_task_long_term_memory.cpython-313.pyc,,
|
||||
agentscope/memory/_reme/__pycache__/_reme_tool_long_term_memory.cpython-313.pyc,,
|
||||
agentscope/memory/_reme/_reme_long_term_memory_base.py,sha256=o9bvTq1Zz4OESBifog0rX-Pax1N4dkcEgbxMknLCnz4,13747
|
||||
agentscope/memory/_reme/_reme_personal_long_term_memory.py,sha256=y4BpRymoNjw4ZHTYE6ThflwDgKroeHOLotgrpCNd5n8,13818
|
||||
agentscope/memory/_reme/_reme_task_long_term_memory.py,sha256=QHqLJojl98JO9Gv4Q6QrJGtyUvffRAIOkY0w0zNkcVo,14324
|
||||
agentscope/memory/_reme/_reme_tool_long_term_memory.py,sha256=DyKOJQYKm5eAhiqd91Xb7bBl23RO6jf0_k98P_AuK7Q,17675
|
||||
agentscope/message/__init__.py,sha256=Bxh_L9v-eHVe4_vrhXhMfaNsk5TN45i0PwuKiIju1I0,519
|
||||
agentscope/message/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/message/__pycache__/_message_base.cpython-313.pyc,,
|
||||
agentscope/message/__pycache__/_message_block.cpython-313.pyc,,
|
||||
agentscope/message/_message_base.py,sha256=sYw8MiuErVEcqaS6mPAoqTwsrJAyb9UqP-hZyqltNYY,6895
|
||||
agentscope/message/_message_block.py,sha256=oJQsnqm2exxIZjUn3j6CV77rlwL-QIbSf15PCGiTOgg,2651
|
||||
agentscope/model/__init__.py,sha256=BrUp6U4Tn7GwuaKvJ4rC3GIwrNXZe9jxBYxftJV7OZA,603
|
||||
agentscope/model/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/model/__pycache__/_anthropic_model.cpython-313.pyc,,
|
||||
agentscope/model/__pycache__/_dashscope_model.cpython-313.pyc,,
|
||||
agentscope/model/__pycache__/_gemini_model.cpython-313.pyc,,
|
||||
agentscope/model/__pycache__/_model_base.cpython-313.pyc,,
|
||||
agentscope/model/__pycache__/_model_response.cpython-313.pyc,,
|
||||
agentscope/model/__pycache__/_model_usage.cpython-313.pyc,,
|
||||
agentscope/model/__pycache__/_ollama_model.cpython-313.pyc,,
|
||||
agentscope/model/__pycache__/_openai_model.cpython-313.pyc,,
|
||||
agentscope/model/__pycache__/_trinity_model.cpython-313.pyc,,
|
||||
agentscope/model/_anthropic_model.py,sha256=DPPI6WF1MD6ApSpu-tFXjM620GE8X3NqF4fpfuquA6U,18902
|
||||
agentscope/model/_dashscope_model.py,sha256=dCY6Z8xYyyMU2Y3HBUHaNaesBBCUW1FDBy_11VIm7dE,19329
|
||||
agentscope/model/_gemini_model.py,sha256=KUCZZelXec7ZXAo_XM8nyjrus7ATY2OYxXRPX0Uze5Y,17453
|
||||
agentscope/model/_model_base.py,sha256=9lRp9WT-NyOsoHLw2pKvr-aBOqsoFp_PLziXz9Jvsho,2039
|
||||
agentscope/model/_model_response.py,sha256=aER8B2-rg_Uu0MRSxknTIO_J0Q5yzyvH1aKfNdaW35k,1295
|
||||
agentscope/model/_model_usage.py,sha256=o9OvCM4CwYqqfa_w2oz80poIU8a2x9tf4jrkynr0g3o,560
|
||||
agentscope/model/_ollama_model.py,sha256=1l2fSIs2AakdZCV6rFVHANpokpZ0ZjAUFheY4sy6Eq0,12319
|
||||
agentscope/model/_openai_model.py,sha256=DA3LspB1X_Z-z9HNsZK_-df6oJjwvUNso1GzpgiRwhw,20201
|
||||
agentscope/model/_trinity_model.py,sha256=aq0pCGcDZfd3OX2bqM0RLhcsD2Dguom2QrwcB3CRjMw,2362
|
||||
agentscope/module/__init__.py,sha256=zhS2IA0PzSZalXiyu1jUXnz32ESQNn7RJKJJuSInE5o,130
|
||||
agentscope/module/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/module/__pycache__/_state_module.cpython-313.pyc,,
|
||||
agentscope/module/_state_module.py,sha256=nI1cm1Sa2ycFiFxs_tpo9aOnxWSqXGr8gVCTlRw5bVI,5644
|
||||
agentscope/pipeline/__init__.py,sha256=KwzeVx8Ugl0Ljk9B_ziRrR-5YfBHtDW5fjdM3CVJmgc,496
|
||||
agentscope/pipeline/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/pipeline/__pycache__/_class.cpython-313.pyc,,
|
||||
agentscope/pipeline/__pycache__/_functional.cpython-313.pyc,,
|
||||
agentscope/pipeline/__pycache__/_msghub.cpython-313.pyc,,
|
||||
agentscope/pipeline/_class.py,sha256=NQS56cj3eOK2j5F28-V3Sdh1cMaOT3N68y10hqH24MY,2594
|
||||
agentscope/pipeline/_functional.py,sha256=lVtm7UijSV7qyJ9C-aR_4dpmTON88nxZ8oUKxpvOoyU,5903
|
||||
agentscope/pipeline/_msghub.py,sha256=P2QqwvwJeiSE82eI_NDszeKHRHV4bOseisTnLwVUT34,5227
|
||||
agentscope/plan/__init__.py,sha256=TZ48k6DSZh5t9piWMl90R-gCBnY0ipLe875ZMfDtKts,418
|
||||
agentscope/plan/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/plan/__pycache__/_in_memory_storage.cpython-313.pyc,,
|
||||
agentscope/plan/__pycache__/_plan_model.cpython-313.pyc,,
|
||||
agentscope/plan/__pycache__/_plan_notebook.cpython-313.pyc,,
|
||||
agentscope/plan/__pycache__/_storage_base.cpython-313.pyc,,
|
||||
agentscope/plan/_in_memory_storage.py,sha256=I32B4nJCu7BYyb1Tgm4QLRI_K0Q27kMNRt96N-y0wLM,2094
|
||||
agentscope/plan/_plan_model.py,sha256=yb4KK_JL1C3QVoX4gCeiSghHFaE39ijq4lxbGm_viZI,6418
|
||||
agentscope/plan/_plan_notebook.py,sha256=LmZOJxQj862Bp4TR_gZU_lqF14uhPHVnENjVLVIOVas,32621
|
||||
agentscope/plan/_storage_base.py,sha256=M1BFqDIiHthFJQFi3gDZNaO12S9FZ_snTFMbqtTipIw,725
|
||||
agentscope/rag/__init__.py,sha256=ZCXDDkeHqYGyl-HuPpWzVj_5mP24fUXSDLpHRc0Hz-U,674
|
||||
agentscope/rag/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/rag/__pycache__/_document.cpython-313.pyc,,
|
||||
agentscope/rag/__pycache__/_knowledge_base.cpython-313.pyc,,
|
||||
agentscope/rag/__pycache__/_simple_knowledge.cpython-313.pyc,,
|
||||
agentscope/rag/_document.py,sha256=9UvKeKu0WBz2nwNj3cgvx6fouVzBa7LJFcDvpVXxw8A,1199
|
||||
agentscope/rag/_knowledge_base.py,sha256=pswLgq1VPKD9UiHns1I_dlI0m6A-9GNyAI67Pm_aJ2A,4441
|
||||
agentscope/rag/_reader/__init__.py,sha256=IvJ2FAphm5CgWoaI1CEPmJPArveQtZv5-Shfkf3yitg,413
|
||||
agentscope/rag/_reader/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/rag/_reader/__pycache__/_image_reader.cpython-313.pyc,,
|
||||
agentscope/rag/_reader/__pycache__/_pdf_reader.cpython-313.pyc,,
|
||||
agentscope/rag/_reader/__pycache__/_reader_base.cpython-313.pyc,,
|
||||
agentscope/rag/_reader/__pycache__/_text_reader.cpython-313.pyc,,
|
||||
agentscope/rag/_reader/__pycache__/_word_reader.cpython-313.pyc,,
|
||||
agentscope/rag/_reader/_image_reader.py,sha256=kY-jLuzaUyILsviOaO4Fzejupa7I_OJGCRVheo-D0YA,1902
|
||||
agentscope/rag/_reader/_pdf_reader.py,sha256=auptyMvJ6CFDOHqF-Z8s6gHoYtA5mldnQsz3k7AfSv8,2758
|
||||
agentscope/rag/_reader/_reader_base.py,sha256=qY5xkACT1H28lWLjUUFB-Dn_xqpUexPwJu-pMViTmVI,900
|
||||
agentscope/rag/_reader/_text_reader.py,sha256=Loq0fFMhj53mhZPcezG_hxIx3LQSD5FaTsxQmXDqZos,5046
|
||||
agentscope/rag/_reader/_word_reader.py,sha256=0eh_7d_Fa5_6g5xsMq7koSWz4Uv6y3fCPY3LoZ958TI,17385
|
||||
agentscope/rag/_simple_knowledge.py,sha256=rMqMEy6QInrjUOX85g8NRlG7LHSrip4hkYVcv17lOMA,2580
|
||||
agentscope/rag/_store/__init__.py,sha256=u7qAWDjacgKxfzIPD7LeDXb9pbvWX6WjgDrdvMyQzJM,305
|
||||
agentscope/rag/_store/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/rag/_store/__pycache__/_milvuslite_store.cpython-313.pyc,,
|
||||
agentscope/rag/_store/__pycache__/_qdrant_store.cpython-313.pyc,,
|
||||
agentscope/rag/_store/__pycache__/_store_base.cpython-313.pyc,,
|
||||
agentscope/rag/_store/_milvuslite_store.py,sha256=1FUs6zlVoOjwz3YLc-oFqyXqSQjEdKD_uNhCDjURqHI,9059
|
||||
agentscope/rag/_store/_qdrant_store.py,sha256=04Xsfr9WM7g7MNRyPO1hEd_-hbIqPkvexYKMY9ukR80,6250
|
||||
agentscope/rag/_store/_store_base.py,sha256=RaXNmcGu6kZMJjM7pfSjVWcv4iCxMt9LMbJpSMrI0ZM,1658
|
||||
agentscope/session/__init__.py,sha256=GY2Skir_T7y19pnywNVBZ3H3ePqsnShva-ljgeiCLiQ,196
|
||||
agentscope/session/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/session/__pycache__/_json_session.cpython-313.pyc,,
|
||||
agentscope/session/__pycache__/_session_base.cpython-313.pyc,,
|
||||
agentscope/session/_json_session.py,sha256=4NvJPK4qplKdASSHeu7BugpCSxO8BNHRbSNPzna6g-s,3820
|
||||
agentscope/session/_session_base.py,sha256=pKbEHnOHJuxaccGobPo2z984W3OrZS3Rl9oCwrpibMY,859
|
||||
agentscope/token/__init__.py,sha256=0PyydmrOKp-Al3CUqM_1WiCSZc9hSR3XEXV7mXCv48k,487
|
||||
agentscope/token/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/token/__pycache__/_anthropic_token_counter.cpython-313.pyc,,
|
||||
agentscope/token/__pycache__/_gemini_token_counter.cpython-313.pyc,,
|
||||
agentscope/token/__pycache__/_huggingface_token_counter.cpython-313.pyc,,
|
||||
agentscope/token/__pycache__/_openai_token_counter.cpython-313.pyc,,
|
||||
agentscope/token/__pycache__/_token_base.cpython-313.pyc,,
|
||||
agentscope/token/_anthropic_token_counter.py,sha256=-1c-OrsfaNvSCEHzgRNSFL7HUQCAuoe9q3nNEk4J9YE,1853
|
||||
agentscope/token/_gemini_token_counter.py,sha256=vcWHo8iHR1JLhDTM3pS6-mpxEUWCKceVll_ypq7mKhU,1385
|
||||
agentscope/token/_huggingface_token_counter.py,sha256=ksxFpqPde16VptiSV8RmHasgld1bp_fz16j6t4baWtk,2846
|
||||
agentscope/token/_openai_token_counter.py,sha256=Aq2YCnCOvPUOfr4r5OeQqqom_VRAPyUdckqIbx3giiQ,11365
|
||||
agentscope/token/_token_base.py,sha256=ukxfNg8nBL_MLd9rzkpy5aP8s-uqEKbeZGtAYZyCBzA,388
|
||||
agentscope/tool/__init__.py,sha256=lXMHKD91iPK2rSY53cDg39kMXwQsedG-rf39gFRd0Go,1020
|
||||
agentscope/tool/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/tool/__pycache__/_async_wrapper.cpython-313.pyc,,
|
||||
agentscope/tool/__pycache__/_registered_tool_function.cpython-313.pyc,,
|
||||
agentscope/tool/__pycache__/_response.cpython-313.pyc,,
|
||||
agentscope/tool/__pycache__/_toolkit.cpython-313.pyc,,
|
||||
agentscope/tool/_async_wrapper.py,sha256=tfv6edszdHC03IsL0Z3EvVAII0zEdYavD3wBI__L-zM,3474
|
||||
agentscope/tool/_coding/__init__.py,sha256=e_XNdZZo6-gS7EvY_AEM2h0q3XtYm1voCKbojypfwn4,232
|
||||
agentscope/tool/_coding/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/tool/_coding/__pycache__/_python.cpython-313.pyc,,
|
||||
agentscope/tool/_coding/__pycache__/_shell.cpython-313.pyc,,
|
||||
agentscope/tool/_coding/_python.py,sha256=FwnidjGPYBRsLGX0FPICjlApISg7eL4GZoVBvFrObik,2714
|
||||
agentscope/tool/_coding/_shell.py,sha256=pgivhc2CSs8mBWSh5ax9NgWI07q_b7WoKV7hdI8h448,2266
|
||||
agentscope/tool/_multi_modality/__init__.py,sha256=H9VpqWCV0V7WXvqqYWjbpwmafJHtq_pDm-RV7P3vG0s,678
|
||||
agentscope/tool/_multi_modality/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/tool/_multi_modality/__pycache__/_dashscope_tools.cpython-313.pyc,,
|
||||
agentscope/tool/_multi_modality/__pycache__/_openai_tools.cpython-313.pyc,,
|
||||
agentscope/tool/_multi_modality/_dashscope_tools.py,sha256=6piJ5fjVaQTYaq4w3UQXGS0ANY29lkCqyc3_keomlbY,8908
|
||||
agentscope/tool/_multi_modality/_openai_tools.py,sha256=UaZOHHAWEi7Y_uG_n23Q8OTh45Cb-hD4t5-oR6o4K_Q,20873
|
||||
agentscope/tool/_registered_tool_function.py,sha256=jI8VMSeWlj-EGq7IKlydBQcC2jjOZEDQTdnkxEm7jng,3449
|
||||
agentscope/tool/_response.py,sha256=3WdPFj1uRdxvkrECfMlUjzPVg-PseeSVNF5SWn1dCOs,938
|
||||
agentscope/tool/_text_file/__init__.py,sha256=tnQP6RCS1wHff65ycZkXE4Fxcw5OXZe50_6dD5hfa9o,276
|
||||
agentscope/tool/_text_file/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/tool/_text_file/__pycache__/_utils.cpython-313.pyc,,
|
||||
agentscope/tool/_text_file/__pycache__/_view_text_file.cpython-313.pyc,,
|
||||
agentscope/tool/_text_file/__pycache__/_write_text_file.cpython-313.pyc,,
|
||||
agentscope/tool/_text_file/_utils.py,sha256=vizy7C6rNmp8z5aiNbrrsMdoeX8bws4FnnyEixlo0jU,2645
|
||||
agentscope/tool/_text_file/_view_text_file.py,sha256=MHq0eiNiBMSDY7Dne8Ch6-YqIS0i8alP3dX2gzxi-nA,2280
|
||||
agentscope/tool/_text_file/_write_text_file.py,sha256=zZcafaRg53o2DT1Q1t9en4Z8sRxaRwREAbsfdLfSpOI,7333
|
||||
agentscope/tool/_toolkit.py,sha256=2iSCpI9zRmNgD_g_PVE-N8K060_DU4S9NDzQ7tvnW30,34654
|
||||
agentscope/tracing/__init__.py,sha256=R7Xegg62pD5UDey0w4ZyAJ6LVt6_qSkjlrOIoV3mHpk,382
|
||||
agentscope/tracing/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/tracing/__pycache__/_attributes.cpython-313.pyc,,
|
||||
agentscope/tracing/__pycache__/_setup.cpython-313.pyc,,
|
||||
agentscope/tracing/__pycache__/_trace.cpython-313.pyc,,
|
||||
agentscope/tracing/__pycache__/_types.cpython-313.pyc,,
|
||||
agentscope/tracing/_attributes.py,sha256=-R_z4rI17u4pOyK9RWtWPmKX0uEL1YmffcJhAEJanvM,1774
|
||||
agentscope/tracing/_setup.py,sha256=QwhHf_NyR-4lBJChNa616pze7CV7HPFq0mNoWxUnCQg,874
|
||||
agentscope/tracing/_trace.py,sha256=Iclrx0Uxpjq4OwrGfCvl_TADn7eSm85R2ZhJiwYdG-w,21677
|
||||
agentscope/tracing/_types.py,sha256=EE-Y6btCihsNuC27XiLlTdqLy1C4CCoENthPDerw8mU,528
|
||||
agentscope/tune/__init__.py,sha256=VpKbNhHLr6GAQ4zJJ-hEy9IOCqLB7YQTNt3DKQKbq0g,195
|
||||
agentscope/tune/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/tune/__pycache__/_tune.cpython-313.pyc,,
|
||||
agentscope/tune/__pycache__/_workflow.cpython-313.pyc,,
|
||||
agentscope/tune/_tune.py,sha256=elVcwVuRRlPghcaYQZAYhiwchV4VqIL-PDb86HaV_ws,2520
|
||||
agentscope/tune/_workflow.py,sha256=TLrri2aRfVamTzDK8FaeHUDDSZZnfhos8JvseeFoHiU,2125
|
||||
agentscope/types/__init__.py,sha256=_AX5wH9fPHkNEwCOQb2ycdh62J6IRXqYYcplJOcWjFQ,408
|
||||
agentscope/types/__pycache__/__init__.cpython-313.pyc,,
|
||||
agentscope/types/__pycache__/_hook.cpython-313.pyc,,
|
||||
agentscope/types/__pycache__/_json.cpython-313.pyc,,
|
||||
agentscope/types/__pycache__/_object.cpython-313.pyc,,
|
||||
agentscope/types/__pycache__/_tool.cpython-313.pyc,,
|
||||
agentscope/types/_hook.py,sha256=st--2oBVuLwNaNk5DQXkYA7xp8X4HaqTaXf2lVDAPM0,427
|
||||
agentscope/types/_json.py,sha256=MXTFO_TufiyRy0X_OuEfuoPqWLRUYRRwurKu-o-m5oI,308
|
||||
agentscope/types/_object.py,sha256=dHR84mJvBFesbYj46mQO9ssw38dPuKpJaCbySprLWZE,111
|
||||
agentscope/types/_tool.py,sha256=J22DtLNDoMTZp_cOkGfrjpmG-qFPWgqaKhcXsyomC58,845
|
||||
@@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: setuptools (80.9.0)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
||||
@@ -0,0 +1,391 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2024 Alibaba
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Some codes of tests/run.py is modified from
|
||||
https://github.com/alibaba/FederatedScope/blob/master/tests/run.py, which is
|
||||
also licensed under the terms of the Apache 2.0.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Code in src/agentscope/web/static/js/socket.io.js is adapted from
|
||||
https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.3/socket.io.js (MIT License)
|
||||
|
||||
Copyright (c) 2014-2021 Guillermo Rauch
|
||||
|
||||
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.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Code in src/agentscope/web/static/js/jquery-3.3.1.min.js is adapted from
|
||||
https://code.jquery.com/jquery-3.3.1.min.js (MIT License)
|
||||
|
||||
Copyright (c) JS Foundation and other contributors
|
||||
|
||||
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.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Code in src/agentscope/web/static/js/bootstrap.bundle.min.js is adapted from
|
||||
https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/js/bootstrap.bundle.min.js
|
||||
(MIT License)
|
||||
|
||||
Copyright (c) 2011-2019 The Bootstrap Authors (https://github
|
||||
.com/twbs/bootstrap/graphs/contributors)
|
||||
|
||||
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.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Code in src/agentscope/web/static/js/bootstrap-table.min.js is adapted from
|
||||
https://unpkg.com/bootstrap-table@1.18.0/dist/bootstrap-table.min.js (MIT
|
||||
License)
|
||||
|
||||
Copyright (c) wenzhixin <wenzhixin2010@gmail.com> (http://wenzhixin.net.cn/)
|
||||
|
||||
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.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Code in src/agentscope/web/static/css/bootstrap.min.css is adapted from
|
||||
https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/css/bootstrap.min.css (MIT
|
||||
License)
|
||||
|
||||
Copyright 2011-2019 The Bootstrap Authors
|
||||
Copyright 2011-2019 Twitter, Inc.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Fonts in src/agentscope/web/static/fonts/KRYPTON.ttf is adapted from
|
||||
https://github.com/githubnext/monaspace (SIL Open Font License 1.1). These
|
||||
fonts are distributed with their original license. See https://github
|
||||
.com/githubnext/monaspace/blob/main/LICENSE for the full text of the license.
|
||||
The following font families are included:
|
||||
|
||||
- Monaspace (with subfamilies: Krypton)
|
||||
|
||||
Copyright (c) 2023, GitHub https://github.com/githubnext/monaspace
|
||||
with Reserved Font Name "Monaspace", including subfamilies: "Argon", "Neon",
|
||||
"Xenon", "Radon", and "Krypton"
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Fonts in src/agentscope/web/static/fonts/OSWALD.ttf is adapted from
|
||||
https://fonts.google.com/specimen/Oswald (SIL Open Font License 1.1). These
|
||||
fonts are distributed with their original license. See https://github
|
||||
.com/googlefonts/OswaldFont/blob/main/OFL.txt for the full text of the license.
|
||||
|
||||
Copyright 2016 The Oswald Project Authors (https://github
|
||||
.com/googlefonts/OswaldFont)
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -0,0 +1 @@
|
||||
agentscope
|
||||
@@ -0,0 +1,133 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""The agentscope serialization module"""
|
||||
import os
|
||||
|
||||
import requests
|
||||
|
||||
from . import exception
|
||||
from . import module
|
||||
from . import message
|
||||
from . import model
|
||||
from . import tool
|
||||
from . import formatter
|
||||
from . import memory
|
||||
from . import agent
|
||||
from . import session
|
||||
from . import embedding
|
||||
from . import token
|
||||
from . import evaluate
|
||||
from . import pipeline
|
||||
from . import tracing
|
||||
from . import rag
|
||||
|
||||
from ._logging import (
|
||||
logger,
|
||||
setup_logger,
|
||||
)
|
||||
from .hooks import _equip_as_studio_hooks
|
||||
from ._version import __version__
|
||||
|
||||
|
||||
def init(
|
||||
project: str | None = None,
|
||||
name: str | None = None,
|
||||
logging_path: str | None = None,
|
||||
logging_level: str = "INFO",
|
||||
studio_url: str | None = None,
|
||||
tracing_url: str | None = None,
|
||||
) -> None:
|
||||
"""Initialize the agentscope library.
|
||||
|
||||
Args:
|
||||
project (`str | None`, optional):
|
||||
The project name.
|
||||
name (`str | None`, optional):
|
||||
The name of the run.
|
||||
logging_path (`str | None`, optional):
|
||||
The path to saving the log file. If not provided, logs will not be
|
||||
saved.
|
||||
logging_level (`str | None`, optional):
|
||||
The logging level. Defaults to "INFO".
|
||||
studio_url (`str | None`, optional):
|
||||
The URL of the AgentScope Studio to connect to.
|
||||
tracing_url (`str | None`, optional):
|
||||
The URL of the tracing endpoint, which can connect to third-party
|
||||
OpenTelemetry tracing platforms like Arize-Phoenix and Langfuse.
|
||||
If not provided and `studio_url` is provided, it will send traces
|
||||
to the AgentScope Studio's tracing endpoint.
|
||||
"""
|
||||
|
||||
from . import _config
|
||||
|
||||
if project:
|
||||
_config.project = project
|
||||
|
||||
if name:
|
||||
_config.name = name
|
||||
|
||||
setup_logger(logging_level, logging_path)
|
||||
|
||||
if studio_url:
|
||||
# Register the run
|
||||
data = {
|
||||
"id": _config.run_id,
|
||||
"project": _config.project,
|
||||
"name": _config.name,
|
||||
"timestamp": _config.created_at,
|
||||
"pid": os.getpid(),
|
||||
"status": "running",
|
||||
# Deprecated fields
|
||||
"run_dir": "",
|
||||
}
|
||||
response = requests.post(
|
||||
url=f"{studio_url}/trpc/registerRun",
|
||||
json=data,
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
from .agent import UserAgent, StudioUserInput
|
||||
|
||||
UserAgent.override_class_input_method(
|
||||
StudioUserInput(
|
||||
studio_url=studio_url,
|
||||
run_id=_config.run_id,
|
||||
max_retries=3,
|
||||
),
|
||||
)
|
||||
|
||||
_equip_as_studio_hooks(studio_url)
|
||||
|
||||
if tracing_url:
|
||||
endpoint = tracing_url
|
||||
else:
|
||||
endpoint = studio_url.strip("/") + "/v1/traces" if studio_url else None
|
||||
|
||||
if endpoint:
|
||||
from .tracing import setup_tracing
|
||||
|
||||
setup_tracing(endpoint=endpoint)
|
||||
|
||||
|
||||
__all__ = [
|
||||
# modules
|
||||
"exception",
|
||||
"module",
|
||||
"message",
|
||||
"model",
|
||||
"tool",
|
||||
"formatter",
|
||||
"memory",
|
||||
"agent",
|
||||
"session",
|
||||
"logger",
|
||||
"embedding",
|
||||
"token",
|
||||
"evaluate",
|
||||
"pipeline",
|
||||
"tracing",
|
||||
"rag",
|
||||
# functions
|
||||
"init",
|
||||
"setup_logger",
|
||||
"__version__",
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""The runtime configuration in agentscope.
|
||||
|
||||
.. note:: You should import this module as ``import ._config``, then use the
|
||||
variables defined in this module, instead of ``from ._config import xxx``.
|
||||
Because when the variables are changed, the changes will not be reflected in
|
||||
the imported module.
|
||||
"""
|
||||
from datetime import datetime
|
||||
|
||||
import shortuuid
|
||||
|
||||
|
||||
def _generate_random_suffix(length: int) -> str:
|
||||
"""Generate a random suffix."""
|
||||
return shortuuid.uuid()[:length]
|
||||
|
||||
|
||||
project = "UnnamedProject_At" + datetime.now().strftime("%Y%m%d")
|
||||
name = datetime.now().strftime("%H%M%S_") + _generate_random_suffix(4)
|
||||
run_id: str = shortuuid.uuid()
|
||||
created_at: str = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
|
||||
trace_enabled: bool = False
|
||||
@@ -0,0 +1,47 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""The logger for agentscope."""
|
||||
|
||||
import logging
|
||||
|
||||
|
||||
_DEFAULT_FORMAT = (
|
||||
"%(asctime)s | %(levelname)-7s | "
|
||||
"%(module)s:%(funcName)s:%(lineno)s - %(message)s"
|
||||
)
|
||||
|
||||
logger = logging.getLogger("as")
|
||||
|
||||
|
||||
def setup_logger(
|
||||
level: str,
|
||||
filepath: str | None = None,
|
||||
) -> None:
|
||||
"""Set up the agentscope logger.
|
||||
|
||||
Args:
|
||||
level (`str`):
|
||||
The logging level, chosen from "INFO", "DEBUG", "WARNING",
|
||||
"ERROR", "CRITICAL".
|
||||
filepath (`str | None`, optional):
|
||||
The filepath to save the logging output.
|
||||
"""
|
||||
if level not in ["INFO", "DEBUG", "WARNING", "ERROR", "CRITICAL"]:
|
||||
raise ValueError(
|
||||
f"Invalid logging level: {level}. Must be one of "
|
||||
f"'INFO', 'DEBUG', 'WARNING', 'ERROR', 'CRITICAL'.",
|
||||
)
|
||||
logger.handlers.clear()
|
||||
logger.setLevel(level)
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(logging.Formatter(_DEFAULT_FORMAT))
|
||||
logger.addHandler(handler)
|
||||
|
||||
if filepath:
|
||||
handler = logging.FileHandler(filepath)
|
||||
handler.setFormatter(logging.Formatter(_DEFAULT_FORMAT))
|
||||
logger.addHandler(handler)
|
||||
|
||||
logger.propagate = False
|
||||
|
||||
|
||||
setup_logger("INFO")
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,285 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""The common utilities for agentscope library."""
|
||||
import asyncio
|
||||
import base64
|
||||
import functools
|
||||
import inspect
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
import types
|
||||
import typing
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Union, Any, Callable, Type, Dict
|
||||
|
||||
import requests
|
||||
from json_repair import repair_json
|
||||
from pydantic import BaseModel
|
||||
|
||||
from .._logging import logger
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from mcp.types import Tool
|
||||
else:
|
||||
Tool = "mcp.types.Tool"
|
||||
|
||||
|
||||
def _json_loads_with_repair(
|
||||
json_str: str,
|
||||
) -> Union[dict, list, str, float, int, bool, None]:
|
||||
"""The given json_str maybe incomplete, e.g. '{"key', so we need to
|
||||
repair and load it into a Python object.
|
||||
"""
|
||||
repaired = json_str
|
||||
try:
|
||||
repaired = repair_json(json_str)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
return json.loads(repaired)
|
||||
except json.JSONDecodeError as e:
|
||||
raise ValueError(
|
||||
f"Failed to decode JSON string `{json_str}` after repairing it "
|
||||
f"into `{repaired}`. Error: {e}",
|
||||
) from e
|
||||
|
||||
|
||||
def _is_accessible_local_file(url: str) -> bool:
|
||||
"""Check if the given URL is a local URL."""
|
||||
return os.path.isfile(url)
|
||||
|
||||
|
||||
def _get_timestamp(add_random_suffix: bool = False) -> str:
|
||||
"""Get the current timestamp in the format YYYY-MM-DD HH:MM:SS.sss."""
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
|
||||
|
||||
if add_random_suffix:
|
||||
# Add a random suffix to the timestamp
|
||||
timestamp += f"_{os.urandom(3).hex()}"
|
||||
|
||||
return timestamp
|
||||
|
||||
|
||||
async def _is_async_func(func: Callable) -> bool:
|
||||
"""Check if the given function is an async function, including
|
||||
coroutine functions, async generators, and coroutine objects.
|
||||
"""
|
||||
|
||||
return (
|
||||
inspect.iscoroutinefunction(func)
|
||||
or inspect.isasyncgenfunction(func)
|
||||
or isinstance(func, types.CoroutineType)
|
||||
or isinstance(func, types.GeneratorType)
|
||||
and asyncio.iscoroutine(func)
|
||||
or isinstance(func, functools.partial)
|
||||
and await _is_async_func(func.func)
|
||||
)
|
||||
|
||||
|
||||
async def _execute_async_or_sync_func(
|
||||
func: Callable,
|
||||
*args: Any,
|
||||
**kwargs: Any,
|
||||
) -> Any:
|
||||
"""Execute an async or sync function based on its type.
|
||||
|
||||
Args:
|
||||
func (`Callable`):
|
||||
The function to be executed, which can be either async or sync.
|
||||
*args (`Any`):
|
||||
Positional arguments to be passed to the function.
|
||||
**kwargs (`Any`):
|
||||
Keyword arguments to be passed to the function.
|
||||
|
||||
Returns:
|
||||
`Any`:
|
||||
The result of the function execution.
|
||||
"""
|
||||
|
||||
if await _is_async_func(func):
|
||||
return await func(*args, **kwargs)
|
||||
|
||||
return func(*args, **kwargs)
|
||||
|
||||
|
||||
def _get_bytes_from_web_url(
|
||||
url: str,
|
||||
max_retries: int = 3,
|
||||
) -> str:
|
||||
"""Get the bytes from a given URL.
|
||||
|
||||
Args:
|
||||
url (`str`):
|
||||
The URL to fetch the bytes from.
|
||||
max_retries (`int`, defaults to `3`):
|
||||
The maximum number of retries.
|
||||
"""
|
||||
for _ in range(max_retries):
|
||||
try:
|
||||
response = requests.get(url)
|
||||
response.raise_for_status()
|
||||
return response.content.decode("utf-8")
|
||||
|
||||
except UnicodeDecodeError:
|
||||
return base64.b64encode(response.content).decode("ascii")
|
||||
|
||||
except Exception as e:
|
||||
logger.info(
|
||||
"Failed to fetch bytes from URL %s. Error %s. Retrying...",
|
||||
url,
|
||||
str(e),
|
||||
)
|
||||
|
||||
raise RuntimeError(
|
||||
f"Failed to fetch bytes from URL `{url}` after {max_retries} retries.",
|
||||
)
|
||||
|
||||
|
||||
def _save_base64_data(
|
||||
media_type: str,
|
||||
base64_data: str,
|
||||
) -> str:
|
||||
"""Save the base64 data to a temp file and return the file path. The
|
||||
extension is guessed from the MIME type.
|
||||
|
||||
Args:
|
||||
media_type (`str`):
|
||||
The MIME type of the data, e.g. "image/png", "audio/mpeg".
|
||||
base64_data (`str):
|
||||
The base64 data to be saved.
|
||||
"""
|
||||
extension = "." + media_type.split("/")[-1]
|
||||
|
||||
with tempfile.NamedTemporaryFile(
|
||||
suffix=f".{extension}",
|
||||
delete=False,
|
||||
) as temp_file:
|
||||
decoded_data = base64.b64decode(base64_data)
|
||||
temp_file.write(decoded_data)
|
||||
temp_file.close()
|
||||
return temp_file.name
|
||||
|
||||
|
||||
def _extract_json_schema_from_mcp_tool(tool: Tool) -> dict[str, Any]:
|
||||
"""Extract JSON schema from MCP tool."""
|
||||
|
||||
return {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": tool.name,
|
||||
"description": tool.description,
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": tool.inputSchema.get(
|
||||
"properties",
|
||||
{},
|
||||
),
|
||||
"required": tool.inputSchema.get(
|
||||
"required",
|
||||
[],
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _remove_title_field(schema: dict) -> None:
|
||||
"""Remove the title field from the JSON schema to avoid
|
||||
misleading the LLM."""
|
||||
# The top level title field
|
||||
if "title" in schema:
|
||||
schema.pop("title")
|
||||
|
||||
# properties
|
||||
if "properties" in schema:
|
||||
for prop in schema["properties"].values():
|
||||
if isinstance(prop, dict):
|
||||
_remove_title_field(prop)
|
||||
|
||||
# items
|
||||
if "items" in schema and isinstance(schema["items"], dict):
|
||||
_remove_title_field(schema["items"])
|
||||
|
||||
# additionalProperties
|
||||
if "additionalProperties" in schema and isinstance(
|
||||
schema["additionalProperties"],
|
||||
dict,
|
||||
):
|
||||
_remove_title_field(
|
||||
schema["additionalProperties"],
|
||||
)
|
||||
|
||||
|
||||
def _create_tool_from_base_model(
|
||||
structured_model: Type[BaseModel],
|
||||
tool_name: str = "generate_structured_output",
|
||||
) -> Dict[str, Any]:
|
||||
"""Create a function tool definition from a Pydantic BaseModel.
|
||||
This function converts a Pydantic BaseModel class into a tool definition
|
||||
that can be used with function calling API. The resulting tool
|
||||
definition includes the model's JSON schema as parameters, enabling
|
||||
structured output generation by forcing the model to call this function
|
||||
with properly formatted data.
|
||||
|
||||
Args:
|
||||
structured_model (`Type[BaseModel]`):
|
||||
A Pydantic BaseModel class that defines the expected structure
|
||||
for the tool's output.
|
||||
tool_name (`str`, default `"generate_structured_output"`):
|
||||
The tool name that used to force the LLM to generate structured
|
||||
output by calling this function.
|
||||
|
||||
Returns:
|
||||
`Dict[str, Any]`: A tool definition dictionary compatible with
|
||||
function calling API, containing type ("function") and
|
||||
function dictionary with name, description, and parameters
|
||||
(JSON schema).
|
||||
|
||||
.. code-block:: python
|
||||
:caption: Example usage
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
class PersonInfo(BaseModel):
|
||||
name: str
|
||||
age: int
|
||||
email: str
|
||||
|
||||
tool = _create_tool_from_base_model(PersonInfo, "extract_person")
|
||||
print(tool["function"]["name"]) # extract_person
|
||||
print(tool["type"]) # function
|
||||
|
||||
.. note:: The function automatically removes the 'title' field from
|
||||
the JSON schema to ensure compatibility with function calling
|
||||
format. This is handled by the internal ``_remove_title_field()``
|
||||
function.
|
||||
"""
|
||||
schema = structured_model.model_json_schema()
|
||||
|
||||
_remove_title_field(schema)
|
||||
tool_definition = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": tool_name,
|
||||
"description": "Generate the required structured output with "
|
||||
"this function",
|
||||
"parameters": schema,
|
||||
},
|
||||
}
|
||||
return tool_definition
|
||||
|
||||
|
||||
def _map_text_to_uuid(text: str) -> str:
|
||||
"""Map the given text to a deterministic UUID string.
|
||||
|
||||
Args:
|
||||
text (`str`):
|
||||
The input text to be mapped to a UUID.
|
||||
|
||||
Returns:
|
||||
`str`:
|
||||
A deterministic UUID string derived from the input text.
|
||||
"""
|
||||
return str(uuid.uuid3(uuid.NAMESPACE_DNS, text))
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user