Agent Neo - Flowith推出的AI Agent,能持续不断地执行任务 | AI工具集

mikel阅读(409)

来源: Agent Neo – Flowith推出的AI Agent,能持续不断地执行任务 | AI工具集

Agent Neo是什么

Agent Neo是Flowith推出的创新 AI Agent。Agent Neo具备无限步骤,无限上下文,无限工具的核心能力,能持续执行复杂任务、处理海量信息和调用多种大模型与工具。Agent Neo 结合 Flowith 的知识库功能,用户上传知识库,能快速构建数字分身或生成高质量内容。Flowith 提供Agent社区,用户能将自己的工作流做成 Recipe 分享到社区里。Agent Neo交互界面美观且富有创意,提供透明化的工作流程,适用于复杂任务自动化、知识管理与分享等场景。Agent Neo目前为邀请制,需激活码使用。

Agent Neo

Agent Neo的主要功能

  • 无限步骤(Unlimited Steps):Agent Neo能进行无限深度的推理,支持持续不断地工作,能执行需要长时间运行的复杂任务。
  • 多步骤优化(Multi-step Refinement):基于多个步骤优化网页,提供最佳的结果。
  • 24/7云端执行(24/7 Cloud Execution):支持全天候云端执行任务,用户的设备处于休眠状态,任务也能不间断地运行。
  • 无限输出长度(Unlimited Output Length):支持生成任意长度的响应,不会出现内容截断的情况。
  • 超智能重新规划(Super-Intelligent Re-Planning):在执行过程中,根据最终目标智能地调整计划。

Agent Neo的官方示例

  • Prompt:Please generate a detailed ‘The Hunger Games’ setting collection, and draw rich and detailed illustrations based on the content of the book. The final presentation form is an immersive experience website with rich animation effects. Please ensure that all key content has correct diagrams. You need to generate relevant content in batches to ensure that each major element has a relevant visual image and picture.(请生成详细的《饥饿游戏》背景集,根据书中的内容绘制丰富而详细的插图。最终呈现形式是一个具有丰富动画效果的沉浸式体验网站。请确保所有关键内容都有正确的图表。你需要批量生成相关内容,确保每个主要元素都有相关的视觉图像和图片。”)

Agent Neo

  • Prompt:introduce flowith 2.0.(介绍 Flowith 2.0)

Agent Neo

Agent Neo的性能表现

Agent Neo 在通用 AI Agent 能力测试 GAIA 中表现出色,刷新所有难度级别的最新最佳性能评分。

Agent Neo

如何使用Agent Neo

  • 获取邀请码:Agent Neo目前为邀请制,需获取激活码后使用。
  • 注册并登录:访问 Flowith 官方网站,完成注册,用邀请码登录。
  • 进入 Agent Neo 模式:在 Flowith 平台中找到打开 Agent Mode,调用 Agent Neo。
  • 设置任务
    • 输入任务描述:告诉 Agent Neo 想要完成的任务,例如生成报告、创建网页、续写故事等。
    • 选择或上传知识库:如果任务需要特定的知识背景,选择已有的知识库或上传相关文档,让 Agent Neo 从中获取信息。
  • 任务规划:Agent Neo 自动规划任务的工作流,包括信息搜集、内容生成、工具调用等。
  • 实时交互:在任务执行过程中,Agent Neo 根据需要与用户交互,例如确认信息、获取反馈或调整任务方向。
  • 查看结果:任务完成后,将结果呈现给用户,例如生成的网页、文档或报告。
  • 修改结果:用户根据需要对生成的内容进行修改或优化,Agent Neo 支持用户直接在可视化界面或代码层面进行调整。
  • 保存工作流:用户将完成的任务保存为工作流(Recipe),方便后续复用或分享给其他用户。
  • 社区分享:将工作流发布到 Flowith 的 Agent 社区,与其他用户共享经验和创意

Agent Neo的应用场景

  • 自动化任务执行:自动执行重复性任务,如数据收集、报告生成和监控任务,提高效率和准确性。
  • 复杂项目管理:基于无限步骤和深度推理来规划和管理项目,直至完成。
  • 内容创作与编辑:续写故事、生成文章或优化网页内容,支持创意写作和多步骤内容精炼。
  • 知识库构建与应用:用户上传和分析知识库,提高任务执行的精准性和效率。
  • 数字分身创建:创建具有专业知识和历史记忆的数字分身,模拟对话或自动化客户服务。

PHP RSA2加密和解密以及接口签名和验签_php rsa和rsa2加密算法-CSDN博客

mikel阅读(252)

来源: PHP RSA2加密和解密以及接口签名和验签_php rsa和rsa2加密算法-CSDN博客

上述代码中,为了演示我给$sign$data两个变量赋值,实际上这两项值是从客户端传递过来的,一般是post提交过来的,这里代码中不做演示了,大家可以自己练习。

运行上述代码后,成功输出“ok”,即验签成功。

以上。

 

本文来源于:helloweba.net

原文链接:https://www.helloweba.net/php/630.html

dify+MCP多应用,构建灵活的AI应用生态系统 - 肖祥 - 博客园

mikel阅读(288)

来源: dify+MCP多应用,构建灵活的AI应用生态系统 – 肖祥 – 博客园

一、概述

前面几篇文章写很多MCP应用,基本上一个dify工作流使用一个MCP应用。

那么一个dify工作流,同时使用多个MCP应用,是否可以呢?答案是可以的。

 

先来看一下效果图

说明:

这里使用了问题分类器,用来判断用户的问题,应该调用哪个MCP应用

AGENT1~4,分别对应一个MCP应用,例如:public-ip-mcp-server,mySQL8-mcp-server,desensitization-mcp-server,searxng-mcp-server

针对mySQL查询输出的内容,会进行脱敏处理。

二、问题分类器

定义

通过定义分类描述,问题分类器能够根据用户输入,使用 LLM 推理与之相匹配的分类并输出分类结果,向下游节点提供更加精确的信息。

场景

常见的使用情景包括客服对话意图分类、产品评价分类、邮件批量分类等。

在一个典型的产品客服问答场景中,问题分类器可以作为知识库检索的前置步骤,对用户输入问题意图进行分类处理,分类后导向下游不同的知识库查询相关的内容,以精确回复用户的问题。

设置

对于比较精确的条件,一般使用条件分支。但是对于我这种场景,条件比较模糊,所以需要使用问题分类器

 

这里定义了3个分类:

公网ip相关问题
mysql 数据库相关查询,涉及学生、教师、成绩、班级、课程等
其他问题

效果如下:

说明:

公网ip相关问题,会直接调用MCP应用public-ip-mcp-server

mySQL相关问题,会调用MCP应用mysql8-mcp-server

其他问题,会调用MCP应用searxng-mcp-server,这个是一个联网搜索引擎,你可以理解为百度,想搜什么都可以。

三、环境说明

dify版本

这里使用的是最新版本1.4.0,如果你的版本没有这么高,1.3.0以上版本也可以。

mcp插件

确保已经安装了以下插件:

Agent 策略(支持 MCP 工具)

MCP SSE / StreamableHTTP

确保插件版本,已经升级到最新版本

mcp应用

这里的所有MCP应用,统一使用Streamable HTTP模式,全部部署在k8s里面。

当然,使用docker运行也是可以的。

mcp插件设置

点击插件MCP SSE / StreamableHTTP,输入MCP 服务配置

完整内容如下:

复制代码
{
    "mysql8-mcp-server": {
        "transport": "streamable_http",
        "url": "http://mysql8-mcp-server-svc.mcp:9000/mcp/",
        "headers": {},
        "timeout": 60
    },
    "desensitization-mcp-server": {
        "transport": "streamable_http",
        "url": "http://desensitization-mcp-server-svc.mcp:9000/mcp/",
        "headers": {},
        "timeout": 60
    },
    "public-ip-mcp-server": {
        "transport": "streamable_http",
        "url": "http://public-ip-mcp-server-svc.mcp:9000/mcp/",
        "headers": {},
        "timeout": 60
    },
    "searxng-mcp-server": {
        "transport": "streamable_http",
        "url": "http://searxng-mcp-server-svc.mcp:9000/mcp/",
        "headers": {},
        "timeout": 60
    }
}
复制代码

注意:这里的url使用的是k8s内部地址,如果使用的是docker方式运行,请根据实际情况修改。

四、public-ip-mcp-server设置

public-ip-mcp-server核心代码如下:

server.py

复制代码
from fastmcp import FastMCP
import json
import requests

mcp = FastMCP("public-ip-address")


@mcp.tool()
def get_public_ip_address() -> str:
    """
    获取公网ip地址
    返回:
        str: 当前网络的公网ip地址
    """
    response = requests.get("http://ip-api.com/json")
    content = json.loads(response.text)
    return content["query"]


if __name__ == "__main__":
    mcp.run(transport="streamable-http", host="0.0.0.0", port=9000, path="/mcp")
复制代码

Agent配置

Agent 1详细配置如下:

MCP服务配置

复制代码
{
  "public-ip-mcp-server": {
        "transport": "streamable_http",
        "url": "http://public-ip-mcp-server-svc.mcp:9000/mcp/",
        "headers": {},
        "timeout": 60
    }
}
复制代码

指令

使用MCP工具,获取服务器公网ip

 

最后直接回复,注意选择变量Agent1 text

 

五、mysql8-mcp-server设置

核心代码

mysql8-mcp-server核心代码如下:

server.py

复制代码
from fastmcp import FastMCP
from mysql.connector import connect, Error
import os

mcp = FastMCP("operateMysql")


def get_db_config():
    """从环境变量获取数据库配置信息

    返回:
        dict: 包含数据库连接所需的配置信息
        - host: 数据库主机地址
        - port: 数据库端口
        - user: 数据库用户名
        - password: 数据库密码
        - database: 数据库名称

    异常:
        ValueError: 当必需的配置信息缺失时抛出
    """

    config = {
        "host": os.getenv("MYSQL_HOST", "localhost"),
        "port": int(os.getenv("MYSQL_PORT", "3306")),
        "user": os.getenv("MYSQL_USER"),
        "password": os.getenv("MYSQL_PASSWORD"),
        "database": os.getenv("MYSQL_DATABASE"),
    }
    print(config)
    if not all(
        [
            config["host"],
            config["port"],
            config["user"],
            config["password"],
            config["database"],
        ]
    ):
        raise ValueError("缺少必需的数据库配置")

    return config


@mcp.tool()
def execute_sql(query: str) -> list:
    """执行SQL查询语句

    参数:
        query (str): 要执行的SQL语句,支持多条语句以分号分隔

    返回:
        list: 包含查询结果的TextContent列表
        - 对于SELECT查询:返回CSV格式的结果,包含列名和数据
        - 对于SHOW TABLES:返回数据库中的所有表名
        - 对于其他查询:返回执行状态和影响行数
        - 多条语句的结果以"---"分隔

    异常:
        Error: 当数据库连接或查询执行失败时抛出
    """
    config = get_db_config()
    try:
        with connect(**config) as conn:
            with conn.cursor() as cursor:
                statements = [stmt.strip() for stmt in query.split(";") if stmt.strip()]
                results = []

                for statement in statements:
                    try:
                        cursor.execute(statement)

                        # 检查语句是否返回了结果集 (SELECT, SHOW, EXPLAIN, etc.)
                        if cursor.description:
                            columns = [desc[0] for desc in cursor.description]
                            rows = cursor.fetchall()

                            # 将每一行的数据转换为字符串,特殊处理None值
                            formatted_rows = []
                            for row in rows:
                                formatted_row = [
                                    "NULL" if value is None else str(value)
                                    for value in row
                                ]
                                formatted_rows.append(",".join(formatted_row))

                            # 将列名和数据合并为CSV格式
                            results.append(
                                "\n".join([",".join(columns)] + formatted_rows)
                            )

                        # 如果语句没有返回结果集 (INSERT, UPDATE, DELETE, etc.)
                        else:
                            conn.commit()  # 只有在非查询语句时才提交
                            results.append(f"查询执行成功。影响行数: {cursor.rowcount}")

                    except Error as stmt_error:
                        # 单条语句执行出错时,记录错误并继续执行
                        results.append(
                            f"执行语句 '{statement}' 出错: {str(stmt_error)}"
                        )
                        # 可以在这里选择是否继续执行后续语句,目前是继续

                return ["\n---\n".join(results)]

    except Error as e:
        print(f"执行SQL '{query}' 时出错: {e}")
        return [f"执行查询时出错: {str(e)}"]


@mcp.tool()
def get_table_name(text: str) -> list:
    """根据表的中文注释搜索数据库中的表名

    参数:
        text (str): 要搜索的表中文注释关键词

    返回:
        list: 包含查询结果的TextContent列表
        - 返回匹配的表名、数据库名和表注释信息
        - 结果以CSV格式返回,包含列名和数据
    """
    config = get_db_config()
    sql = "SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_COMMENT "
    sql += f"FROM information_schema.TABLES WHERE TABLE_SCHEMA = '{config['database']}' AND TABLE_COMMENT LIKE '%{text}%';"
    return execute_sql(sql)


@mcp.tool()
def get_table_desc(text: str) -> list:
    """获取指定表的字段结构信息

    参数:
        text (str): 要查询的表名,多个表名以逗号分隔

    返回:
        list: 包含查询结果的列表
        - 返回表的字段名、字段注释等信息
        - 结果按表名和字段顺序排序
        - 结果以CSV格式返回,包含列名和数据
    """
    config = get_db_config()
    # 将输入的表名按逗号分割成列表
    table_names = [name.strip() for name in text.split(",")]
    # 构建IN条件
    table_condition = "','".join(table_names)
    sql = "SELECT TABLE_NAME, COLUMN_NAME, COLUMN_COMMENT "
    sql += (
        f"FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '{config['database']}' "
    )
    sql += f"AND TABLE_NAME IN ('{table_condition}') ORDER BY TABLE_NAME, ORDINAL_POSITION;"
    return execute_sql(sql)


@mcp.tool()
def get_lock_tables() -> list:
    """
    获取当前mysql服务器InnoDB 的行级锁

    返回:
        list: 包含查询结果的TextContent列表
    """
    sql = """SELECT
    p2.`HOST` AS 被阻塞方host,
    p2.`USER` AS 被阻塞方用户,
    r.trx_id AS 被阻塞方事务id,
    r.trx_mysql_thread_id AS 被阻塞方线程号,
    TIMESTAMPDIFF(SECOND, r.trx_wait_started, CURRENT_TIMESTAMP) AS 等待时间,
    r.trx_query AS 被阻塞的查询,
    l.OBJECT_NAME AS 阻塞方锁住的表,
    m.LOCK_MODE AS 被阻塞方的锁模式,
    m.LOCK_TYPE AS '被阻塞方的锁类型(表锁还是行锁)',
    m.INDEX_NAME AS 被阻塞方锁住的索引,
    m.OBJECT_SCHEMA AS 被阻塞方锁对象的数据库名,
    m.OBJECT_NAME AS 被阻塞方锁对象的表名,
    m.LOCK_DATA AS 被阻塞方事务锁定记录的主键值,
    p.`HOST` AS 阻塞方主机,
    p.`USER` AS 阻塞方用户,
    b.trx_id AS 阻塞方事务id,
    b.trx_mysql_thread_id AS 阻塞方线程号,
    b.trx_query AS 阻塞方查询,
    l.LOCK_MODE AS 阻塞方的锁模式,
    l.LOCK_TYPE AS '阻塞方的锁类型(表锁还是行锁)',
    l.INDEX_NAME AS 阻塞方锁住的索引,
    l.OBJECT_SCHEMA AS 阻塞方锁对象的数据库名,
    l.OBJECT_NAME AS 阻塞方锁对象的表名,
    l.LOCK_DATA AS 阻塞方事务锁定记录的主键值,
    IF(p.COMMAND = 'Sleep', CONCAT(p.TIME, ' 秒'), 0) AS 阻塞方事务空闲的时间
    FROM performance_schema.data_lock_waits w
    INNER JOIN performance_schema.data_locks l ON w.BLOCKING_ENGINE_LOCK_ID = l.ENGINE_LOCK_ID
    INNER JOIN performance_schema.data_locks m ON w.REQUESTING_ENGINE_LOCK_ID = m.ENGINE_LOCK_ID
    INNER JOIN information_schema.INNODB_TRX b ON b.trx_id = w.BLOCKING_ENGINE_TRANSACTION_ID
    INNER JOIN information_schema.INNODB_TRX r ON r.trx_id = w.REQUESTING_ENGINE_TRANSACTION_ID
    INNER JOIN information_schema.PROCESSLIST p ON p.ID = b.trx_mysql_thread_id
    INNER JOIN information_schema.PROCESSLIST p2 ON p2.ID = r.trx_mysql_thread_id
    ORDER BY 等待时间 DESC;"""

    return execute_sql(sql)


if __name__ == "__main__":
    mcp.run(transport="streamable-http", host="0.0.0.0", port=9000, path="/mcp")
复制代码

Agent配置

Agent 2详细配置如下:

 

MCP服务配置

复制代码
{
    "mysql8-mcp-server": {
        "transport": "streamable_http",
        "url": "http://mysql8-mcp-server-svc.mcp:9000/mcp/",
        "timeout": 60
    }
}
复制代码

指令

 View Code

 

六、desensitization-mcp-server设置

核心代码

desensitization-mcp-server核心代码如下:

server.py

 View Code

Agent配置

Agent 4详细配置如下:

注意:查询要选择变量Agent 2 text

 

MCP服务配置

复制代码
{ 
  "desensitization-mcp-server": {
        "transport": "streamable_http",
        "url": "http://desensitization-mcp-server-svc.mcp:9000/mcp/",
        "headers": {},
        "timeout": 60
    }
}
复制代码

指令

使用MCP工具,对文本进行脱敏处理

 

最后直接回复,注意选择变量Agent4 text

 

七、searxng-mcp-server设置

核心代码

searxng-mcp-server核心代码如下:

server.py

复制代码
from fastmcp import FastMCP
import requests
import os

mcp = FastMCP("searxng")


@mcp.tool()
def search(query: str) -> str:
    """
    搜索关键字,调用searxng的API接口
    参数:
        query (str): 要搜索的关键词
    返回:
        str: 查询结果
    """
    api_server = os.getenv("API_SERVER", None)
    if not api_server:
        print("缺少必需的API_SERVER配置")
        raise ValueError("缺少必需的API_SERVER配置")

    # API URL
    url = "%s/search?q=%s&format=json" % (api_server, query)
    print(url)

    try:
        # 发送GET请求
        response = requests.get(url)

        # 检查请求是否成功
        if response.status_code == 200:
            # 将响应内容解析为JSON
            data = response.json()
            # print("JSON内容:")
            # print(data,type(data))
            result_list = []
            for i in data["results"]:
                # print(i["content"])
                result_list.append(i["content"])
            content = "\n".join(result_list)
            # print(content)
            return content
        else:
            print(f"请求失败,状态码: {response.status_code}")
            return False

    except requests.exceptions.RequestException as e:
        print(f"请求过程中发生错误: {e}")
        return False


if __name__ == "__main__":
    mcp.run(transport="streamable-http", host="0.0.0.0", port=9000, path="/mcp")
复制代码

Agent配置

Agent 3详细配置如下:

MCP服务配置

复制代码
{
  "searxng-mcp-server": {
        "transport": "streamable_http",
        "url": "http://searxng-mcp-server-svc.mcp:9000/mcp/",
        "headers": {},
        "timeout": 60
    }
}
复制代码

指令

复制代码
## 技能
### 技能1:使用MCP工具进行联网搜索,获取到的相关内容进行总结分析
## 限制
- 如果没有相关内容,再进行联网搜索
- 你的回答应严格针对分析任务。使用结构化语言,逐步思考
- 使用的语言应和用户提问的语言相同
- 搜索的关键词必须和用户提问的内容一致
复制代码

 

最后直接回复,注意选择变量Agent3 text

八、dify测试

点击右上角的预览按钮

公网ip多少

注意:这里可以看到绿色的连接线条,可以清晰的看到工作流的走向,它确实是按照我预期的方向在走。

 

李华的老师,查询一下个人详细信息

可以看到通过问题分类器,分别走向AGENT 2,AGENT 4,最终得到的答案,是进行了脱敏处理。

上海今天天气如何

这里直接联网搜索答案了

 

PHP发送/接收JSON请求_php header location 能发送 json吗-CSDN博客

mikel阅读(226)

来源: PHP发送/接收JSON请求_php header location 能发送 json吗-CSDN博客

现在API模式,经常使用headers里传JSON数据,作为POST请求传递参数的方式,在参数量较多时POST JSON要比POST FormData便于开发和测试

PHP发送JSON POST
$url = “http://example.com/request/post/json”;
$data = json_encode([“foo” => “bar”]);
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(“Content-type: application/json”));
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_exec($curl);
curl_close($curl);
或者

/**
* PHP发送Json对象数据
* 例子 list($returnCode, $returnContent) = http_post_json($url, $jsonStr);
* @param $url 请求url
* @param $jsonStr 发送的json字符串
* @return array
*/
function http_post_json($url, $jsonStr)
{

$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
‘Content-Type: application/json; charset=utf-8’,
‘Content-Length: ‘ . strlen($jsonStr)
)
);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

return array($httpCode, $response);

}
PHP接受JSON POST
$data = json_decode(file_get_contents(‘php://input’), true);
php://input 是个可以访问请求的原始数据的只读流。 POST 请求的情况下,最好使用 php://input 来代替

$GLOBALS[‘HTTP_RAW_POST_DATA’]
,因为它不依赖于特定的 php.ini 指令。 而且,这样的情况下

$GLOBALS[‘HTTP_RAW_POST_DATA’]
默认没有填充, 比激活 always_populate_raw_post_data 潜在需要更少的内存。 enctype=”multipart/form-data” 的时候 php://input 是无效的。

在 PHP 5.6 之前 php://input 打开的数据流只能读取一次; 数据流不支持 seek 操作。 不过,依赖于 SAPI 的实现,请求体数据被保存的时候, 它可以打开另一个 php://input 数据流并重新读取。 通常情况下,这种情况只是针对 POST 请求,而不是其他请求方式,比如 PUT 或者 PROPFIND。
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/yule117737767/article/details/119138023

Intellij IDEA 打包jar的多种方式-CSDN博客

mikel阅读(328)

来源: Intellij IDEA 打包jar的多种方式-CSDN博客

IDEA打包jar包的多种方式

用IDEA自带的打包形式
用Maven插件maven-shade-plugin打包
用Maven插件maven-assembly-plugin打包
用IDEA自带的打包形式
1.File->Project Structure->Artifacts->Add->Jar->From modules with dependencies

2.配置
第一步选择Main函数执行的类。
第二步选择如图的选项,目的是对第三方Jar包打包时做额外的配置,如果不做额外的配置可不选这个选项(但不保证打包成功)
第三步需要在src/main目录下,新建一个resources目录,将MANIFEST.MF文件保存在这里面,因为如果用默认缺省值的话,在IDEA12版本下会有bug。

 

点击ok

3.把第三方jar包放入lib目录

 

4.build

 

5.在out/artifacts目录下生成jar包

用maven-shade-plugin打包
上面的打包过程实在是过于的繁琐,而且也没有利用到maven管理项目的特色。为此,我们这里利用maven中的maven-shade-plugin插件。在pom.xml中,我们加入如下的信息来加入插件。

1.加入maven-shade-plugin插件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation=”org.apache.maven.plugins.shade.resource.ManifestResourceTransformer”>
<mainClass>Main.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>

这里面配置了一个`configuration`标签内容,在此标签下面 有一个transformer标签,用来配置Main函数的入口( <mainClass>Main.Main</mainClass>),当然此标签内容很复杂,不是上面写的那么简单,上面之所以如此简单,是因为在所有类中(包括第三方Jar)只有一个Main方法。如果第三方jar中有Main方法,就要进行额外的配置,上面这么配置,不一定能执行成功。

2.使用maven命令打包
mvn clean compile //清除之前target编译文件并重新编译
mvn clean package //对项目进行打包(因为配置过插件,所以jar包是可执行的)
mvn clean install //安装项目,然后就可以使用了

可以通过自带的maven管理工具代替执行上面的命令

 

注意: 想要忽略测试用例

mvn package -DskipTests

或者

mvn package -Dmaven.test.skip=true

maven.test.skip同时控制maven-compiler-plugin和maven-surefire-plugin两个插件的行为,即跳过编译,又跳过测试

也可以使用插件

<plugin>
<groupId>org.apahce.maven.plugins<groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<includes>
<include>**/*Tests.java</include>
</includes>
</configuration>
</plugin>

使用* / Test.Java 来匹配所有以Tests结尾的Java类。两个星号*用来匹配任意路径,一个星号用来获取除路径风格符外的0个或多个字符。还可使用excludes来排除Test类

在target/目录下生成jar包

 

使用java -jar xxx.jar运行即可

用maven-assembly-plugin打包
上面的方法,我们还需要点击很多命令去打包。这次利用一个新的插件,可以打包更简单。同样,在pom.xml中加入如下代码。上文的maven-shade-plugin插件代码可以删除。最好不要写2个插件代码。

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<descriptors>
<descriptor>src/main/resources/assembly.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>Main.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>

<assembly>
<id>j2se-assembly</id>
<formats>
<format>jar</format>
</formats>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>

这里同样配置了一个manifest标签来配置Main函数的入口。然后通过如下指令来实现打包。

mvn assembly:assembly
或者

========使用mvn assembly:assembly运行会出现Error reading assemblies: No assembly descriptors found 异常,但是使用mvn package命令打包没问题 不知道为什么(꒪⌓꒪)=======
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/Thousa_Ho/article/details/72799871

【JAVA】使用intellij IDEA将项目打包为jar包_idea打包jar文件-CSDN博客

mikel阅读(299)

来源: 【JAVA】使用intellij IDEA将项目打包为jar包_idea打包jar文件-CSDN博客

当你有一个能正常编译的项目,以springboot为例,有两步步骤

打包配置
打包
一、打包配置
1.点击右上角快捷按钮/文件–>项目结构,打开项目结构设置

 

2.项目结构–>Artifacts,如图所示选择

3.在Create JAR from Modules配置,

5.配置jar输出相关设置

二、打包
1.构建–>Build Artifacts

2.选择Build即可

然后可以在设置的输出路径查看打的jar包

我设置的输出路径为 C:\Users\admin\Desktop\kantools\target

 

使用java -jar 运行看看

!注意:这个方式是jar内不包含第三方的依赖的,如果想做成和第三方依赖一起打包的,建议使用maven工具
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/ET1131429439/article/details/119907638

一步到位——Node版本管理神器nvm安装教程(2024最新)-CSDN博客

mikel阅读(639)

来源: 一步到位——Node版本管理神器nvm安装教程(2024最新)-CSDN博客

前言
Node的安装是许多学习前端的小伙伴的必经之路,我们可能会遇到需要切换node版本的情况,卸载node再安装另一个显然不够优雅,因此nvm的出现极大提高我们切换node的效率。
然而,在nvm的安装过程中有很多坑,许多新手非常容易踩雷,那么接下来让我带领你们,一次到位安装nvm,包能用,包提醒哪里有坑,只要你按我说的一步一步做即可,记得点赞收藏一波哈!

为保证一次包过,所有cmd操作请用❗管理员身份❗运行

 

一、下载nvm
1. 发行版本地址
https://github.com/coreybutler/nvm-windows/releases
在这里可以查看到所有发行版本

 

2. 如何选择版本,为什么❓
现在是2024年,已经更新到1.1.12版本了,那么我们该选择哪个版本呢?这里我的建议是使用最新版本即可

3. 值得点赞的贴心下载链接
我们选择zip版本的压缩包下载即可,在压缩包里面是一个exe文件,在这里我也把链接放上,方便小伙伴一步到位下载,Github下载缓慢可以使用迅雷等P2P下载工具(直接复制链接打开迅雷即可弹出下载弹窗,没有就点击新建)

经典版(❗暂不推荐)
https://github.com/coreybutler/nvm-windows/releases/download/1.1.7/nvm-setup.zip

最新版(推荐,截止2024.07)
https://github.com/coreybutler/nvm-windows/releases/download/1.1.12/nvm-setup.zip

 

二、删除已有的Node.js
⭕Tips:如果你的电脑还没有安装Node.js,则这一步可以跳过

1. 为什么要卸载呢❓
这是因为如果不卸载的话,有可能安装不成功,如下图2所示,在安装的版本过程中,如果不事先卸载已安装的版本的话,则nvm安装程序也会提示在安装nvm之前必须先卸载已安装的Node.js,所以呢,如果我们所以呢我们就不要心疼了,直接大大方方卸载就行~

 

那么在哪里卸载呢?

2. 在控制面板卸载Node.js
按下Win键,直接键盘输入控制面板的拼音即可,或者Win + R打开运行输入control回车也行

 

然后点击卸载程序

 

然后我们找到Node.js

 

双击,然后选是,卸载即可

 

好的,这一步我们就卸载完了,打开cmd,输入node,这时候也提示

‘node’ 不是内部或外部命令,也不是可运行的程序或批处理文件。

说明我们已经卸载完毕

 

三、安装nvm
1. 同意用户协议
双击exe文件,选择I accept the agreement,然后next

 

接下来是选择安装目录,这一步我们一般默认即可

2. 选择nvm安装目录
但是要注意了❗如果要修改的话,安装路径中,文件夹不能含有中文和空格,推荐选择一个没有中文或者空格的安装目录,这一点特别注意,路径必须全英文,不含有任何中文字符,这一点在初学者中很容易犯错,比如D:\软件\nvm、C:\Users\坤坤\nvm ,都是不推荐的,后续使用过程中一般会报错

 

报错示例
nvm安装目录包含中文的话,执行后续指令的时候,会报这个错

 

 

如果实在不小心安装在中文目录的话,则卸载重来即可

3. 选择nodejs的安装目录
下一步是选择Node.js的安装目录,这里直接默认即可,但如果你有HarmonyOS APP开发需要的话,路径不能带空格,需要选择新的目录

 

报错示例
Node.js安装目录包含中文的话,执行后续指令的时候,会报这个错

 

 

4. Install
然后直接install即可

 

5. 安装完成
点击Finish完成安装

 

四、配置nvm镜像
1. 寻找安装目录
我们打开cmd,输入 nvm ,可以看到打印出了nvm的指令列表,说明nvm安装成功

 

我们输入 nvm root 查看nvm的安装目录

 

默认情况在这个位置,如果你是旧版cmd的话,直接选择这段路径,回车即可复制或者 Ctrl + Insert(Ins),新版终端则使用 Ctrl + C

C:\Users\你的用户名\AppData\Roaming\nvm

然后我们按下Win键直接Ctrl + V粘贴即可

 

2. 修改配置
打开安装目录后,直接编辑settings.txt即可

 

 

加入以下配置,Ctrl + S保存即可

 

不再推荐使用旧域名
node_mirror: https://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/

推荐新的淘宝镜像域名👍

node_mirror: https://npmmirror.com/mirrors/node/
npm_mirror: https://npmmirror.com/mirrors/npm/
1
2
或者使用命令行设置
nvm npm_mirror https://npmmirror.com/mirrors/npm/
nvm node_mirror https://npmmirror.com/mirrors/node/
1
2
五、使用nvm
注意❗,我们先关闭cmd,然后重新打开一个

1. 查看可用版本
输入以下格式的指令

nvm list available
1

可以查看到最近的版本和LTS长期支持版,如果要查看全部版本则可以到以下网址查看所有发行版本

https://nodejs.org/download/release

 

2. 安装Node.js
输入以下格式的指令

nvm install 版本号
1
版本号可以是主版本,也可以是指定某个版本
例如 nvm install 20,nvm install 20.11.0

一般来说,在配置了淘宝镜像之后,下载速度很快,如果下载很慢的话,有可能是没有配置镜像或者网络波动

 

3. 使用对应的版本
nvm use 版本号
1
例如 nvm use 20

 

现在就切换到了Node.js 20版本

4. 查看npm版本
npm -v
1

5. npm升级降级安装
npm install npm@版本号
1
例如 npm i npm@6

 

6. 多版本管理
查看下载的Node.js版本列表
nvm ls
1

Currently using 64-bit executable 表示当前使用的版本

卸载某个版本
nvm uninstall 版本号
1
7. 附录:常用指令
nvm-arch #显示节点是以32位还是64位模式运行。

nvm install<version>[arch]
#版本可以是node.js版本,也可以是“最新”的最新稳定版本。
#(可选)指定是安装32位版本还是64位版本(默认为system arch)。
#将[arch]设置为“all”以安装32 AND 64位版本。
#在该命令的末尾添加–unsecurity,以绕过远程下载服务器的SSL验证。

nvm list[可用] # 列出node.js的安装。在末尾键入“available”(可用),查看可以安装的内容。别名为ls。

nvm on #启用node.js版本管理。

nvm off #禁用node.js版本管理。

nvm proxy [url]
#设置用于下载的代理。将[url]留空以查看当前代理。
#将[url]设置为“none”以删除代理。

nvm node_mirror [url] #设置节点镜像。默认为https://nodejs.org/dist/.将[url]留空以使用默认url。

nvm npm_mirror [url] #设置npm镜像。默认为https://github.com/npm/cli/archive/.将[url]留空为默认url。

nvm uninstall <version> #版本必须是特定的版本。

nvm use [version] [arch]
#切换到使用指定的版本。可选择指定32/64位体系结构。
#nvm使用<arch>将继续使用所选版本,但切换到32/64位模式。
#nvm-root[path]:设置nvm应存储不同版本node.js的目录。
#如果未设置<path>,则会显示当前根目录。

nvm version #显示用于Windows的nvm的当前运行版本。别名为v。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
文档:https://github.com/coreybutler/nvm-windows/blob/master/README.md

拓展阅读
1.使用nrm管理npm镜像源,加速下载
npm i -g nrm
1

使用淘宝镜像

nrm use taoabo
1
查看镜像源列表

nrm ls
1

2.安装pnpm
nodejs版本需要16.14以上,推荐18或者20等最新LTS版本

npm i -g pnpm
1
更新pnpm

npm i -g pnpm
1
推荐阅读
必看!VSCode字体界面美化教程
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/m0_46491549/article/details/129750694

IntelliJ IDEA 安装、配置和使用Lombok插件 - gdjlc - 博客园

mikel阅读(255)

来源: IntelliJ IDEA 安装、配置和使用Lombok插件 – gdjlc – 博客园

Lombok 可用来帮助开发人员消除 Java 的重复代码,尤其是对于简单的 Java 对象(POJO),比如说getter/setter/toString等方法的编写。它通过注解实现这一目的。
官网:https://projectlombok.org
下面是IntelliJ IDEA安装、配置和使用Lombok插件的过程。

一、安装Lombok插件

菜单栏File -> Settings -> Plugins,在中间Marketplace下面输入Lombok搜索后进行安装,安装后会提示重启IDEA。下面是已经安装后的截图。

二、配置注解处理器

菜单栏File -> Settings -> Plugins -> Build,Execution,Deployment -> Compiler -> Annotation Processors,勾选Enable annotation processing并保存。

三、使用Lombok插件

1、pom.xml加入依赖,当前最新版本是1.18.10。

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>

2、缩写一个简单的实体类,在类名上加上注解@Data,在.class文件生成类中所有属性的get/set方法、equals、canEqual、hashCode、toString方法等

import lombok.Data;

@Data
public class User {
    private Integer userId;
}

菜单栏点击View -> Tool Windows -> Structure 就可以看到类中所有方法。

使用离线部署32B模型实现OpenDeepWiki项目代码自动分析与文档生成 - 239573049 - 博客园

mikel阅读(816)

来源: 使用离线部署32B模型实现OpenDeepWiki项目代码自动分析与文档生成 – 239573049 – 博客园

背景介绍

在企业环境中,我们经常需要对公司项目代码进行分析和文档生成。然而,考虑到代码的保密性,将代码上传至公共AI平台存在安全隐患。为解决这一问题,我们可以在公司内部GPU服务器上部署强大的大语言模型(如qwen2.5:32b-instruct-fp16),并结合OpenDeepWiki工具,实现安全、高效的代码仓库分析与文档自动生成。

环境需求

  • 硬件: 支持qwen2.5:32b-instruct-fp16模型运行的GPU服务器(推荐配置:4*RTX 3090)
  • 软件: Ollama(用于部署模型)、Docker和Docker Compose环境
  • 网络: 内部网络环境,确保安全性

部署步骤

1. 部署OpenDeepWiki

在服务器上创建并配置必要文件:

docker-compose.yml:

services:
koalawiki:
image: crpi-j9ha7sxwhatgtvj4.cn-shenzhen.personal.cr.aliyuncs.com/koala-ai/koala-wiki
environment:
KOALAWIKI_REPOSITORIES=/repositories
TASK_MAX_SIZE_PER_USER=5 # 每个用户AI处理文档生成的最大数量
REPAIR_MERMAID=1 # 是否进行Mermaid修复,1修复,其余不修复
CHAT_MODEL=qwen2.5:32b-instruct-fp16 # 必须要支持function的模型
ANALYSIS_MODEL=qwen2.5:32b-instruct-fp16 # 分析模型,用于生成仓库目录结构,这个很重要,模型越强,生成的目录结构越好,为空则使用ChatModel
CHAT_API_KEY=sk- #您的APIkey
LANGUAGE=简体中文 # 设置生成语言默认为”中文”
ENDPOINT=http://您的Ollamaip:11434/v1
DB_TYPE=SQLite
DB_CONNECTION_STRING=Data Source=/data/KoalaWiki.db
UPDATE_INTERVAL=5 # 仓库增量更新间隔,单位天
EnableSmartFilter=true # 是否启用智能过滤,这可能影响AI得到仓库的文件目录
PARALLEL_COUNT=1 # The warehouse processes the quantity in parallel
volumes:
./repositories:/app/repositories
./data:/data
koalawiki-web:
image: crpi-j9ha7sxwhatgtvj4.cn-shenzhen.personal.cr.aliyuncs.com/koala-ai/koala-wiki-web
environment:
NEXT_PUBLIC_API_URL=http://koalawiki:8080 # 用于提供给server的地址
nginx: # 需要nginx将前端和后端代理到一个端口
image: crpi-j9ha7sxwhatgtvj4.cn-shenzhen.personal.cr.aliyuncs.com/koala-ai/nginx:alpine
ports:
8090:80
volumes:
./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
koalawiki
koalawiki-web

nginx.conf:

server {
listen 80;
server_name localhost;
# 设置上传文件大小限制为 100MB
client_max_body_size 100M;
# 日志配置
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# 代理所有 /api/ 请求到后端服务
location /api/ {
proxy_pass http://koalawiki:8080/api/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection ‘upgrade’;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
# 其他所有请求转发到前端服务
location / {
proxy_pass http://koalawiki-web:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection ‘upgrade’;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}

2. 启动服务

创建好上述文件后,在同级目录下执行以下命令:

  1. 拉取必要的镜像:
    docker-compose pull
  2. 启动容器:
    docker-compose up -d
  3. 等待服务初始化完成(通常需要几分钟)

3. 访问OpenDeepWiki平台

在浏览器中访问 http://[服务器IP]:8090,即可看到OpenDeepWiki的界面:

使用指南

添加代码仓库进行分析

  1. 从以下地址获取OpenDeepWiki源码(推荐国内用户使用Gitee):
  2. 下载源码的ZIP压缩包
  3. 在OpenDeepWiki平台点击”添加新仓库”:

  1. 选择”上传压缩包”,填写组织名称和仓库名称(这些字段必填,将影响前端路由显示),然后提交:

  1. 上传完成后,系统将开始处理仓库(处理时间约为3-5分钟)。处理中的仓库会显示在列表中:

  1. 处理完成后,点击仓库名称即可查看由qwen2.5:32b-instruct-fp16模型自动生成的文档:

系统优势

  • 安全可控:所有代码分析和文档生成过程都在内部环境完成,确保代码安全
  • 高质量文档:借助强大的qwen2.5:32b-instruct-fp16模型,生成的文档结构清晰、内容全面
  • 一键操作:简单的上传流程,无需复杂配置
  • 可扩展性:支持多种代码仓库格式,适用于不同项目需求

结语

通过部署OpenDeepWiki与qwen2.5:32b-instruct-fp16模型,我们可以安全、高效地为公司代码仓库生成完整文档,大幅提升项目理解和开发效率。

如果您对OpenDeepWiki感兴趣,欢迎访问以下地址并给项目点个Star:

在线体验地址https://opendeep.wiki/
目前已有500+仓库加入!您也可以将您的开源仓库添加进来。

Unity+MediaPipe虚拟试衣间技术实现全攻略 - TechSynapse - 博客园

mikel阅读(270)

来源: Unity+MediaPipe虚拟试衣间技术实现全攻略 – TechSynapse – 博客园

引言:数字时尚革命的序章

在元宇宙概念席卷全球的今天,虚拟试衣技术正成为连接物理世界与数字孪生的关键桥梁。本文将深入解析基于Unity引擎结合MediaPipe姿态估计框架的虚拟试衣系统实现,涵盖从环境搭建到完整AR试穿界面开发的全流程,最终实现支持实时人体追踪、多服装物理模拟及用户反馈的完整解决方案。

一、技术选型与架构设计

1.1 技术栈组合逻辑

  • Unity 3D引擎:跨平台渲染核心,提供物理引擎(PhysX)和AR Foundation框架。
  • MediaPipe:Google开源的跨平台ML解决方案,提供实时人体姿态估计。
  • TensorFlow.js:浏览器端轻量化ML推理(可选)。
  • Python后端:模型训练与数据处理。
  • C#:Unity主逻辑开发语言。

1.2 系统架构图

[摄像头输入][MediaPipe姿态估计][骨骼数据标准化][Unity场景][服装资源管理][物理模拟引擎][AR试穿界面][用户反馈系统]

二、开发环境配置

2.1 MediaPipe环境搭建(Python端)

# 创建Python虚拟环境
python -m venv venv_mediapipe
source venv_mediapipe/bin/activate  # Linux/Mac
# venv_mediapipe\Scripts\activate  # Windows
 
# 安装依赖包
pip install mediapipe==0.10.5 opencv-python==4.8.1.78

2.2 Unity项目配置

  1. 创建新3D项目(推荐使用URP渲染管线)。
  2. 导入必备包:
    • AR Foundation (4.3.0+);
    • ARCore XR Plugin (5.2.0+);
    • ARKit XR Plugin (5.2.0+);
  3. 安装NuGet for Unity(用于C#与Python交互)。

三、核心模块实现

3.1 MediaPipe姿态估计集成

3.1.1 Python姿态检测服务端

# server.py
import cv2
import mediapipe as mp
import socket
import json
import numpy as np
 
mp_pose = mp.solutions.pose
pose = mp_pose.Pose(static_image_mode=False,
                   model_complexity=2,
                   enable_segmentation=True,
                   min_detection_confidence=0.5)
 
def process_frame(frame):
    results = pose.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
    if results.pose_landmarks:
        landmarks = []
        for lm in results.pose_landmarks.landmark:
            landmarks.append({
                "x": lm.x,
                "y": lm.y,
                "z": lm.z,
                "visibility": lm.visibility
            })
        return json.dumps({"landmarks": landmarks})
    return None
 
# 启动TCP服务器
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind(('localhost', 65432))
    s.listen()
    conn, addr = s.accept()
    with conn:
        cap = cv2.VideoCapture(0)
        while cap.isOpened():
            ret, frame = cap.read()
            if not ret:
                break
            data = process_frame(frame)
            if data:
                conn.sendall(data.encode())

3.1.2 Unity客户端接收

// PoseReceiver.cs
using System.Net.Sockets;
using System.Text;
using UnityEngine;
 
public class PoseReceiver : MonoBehaviour
{
    private TcpClient client;
    private NetworkStream stream;
    
    void Start()
    {
        client = new TcpClient("localhost", 65432);
        stream = client.GetStream();
    }
 
    void Update()
    {
        if (stream.DataAvailable)
        {
            byte[] data = new byte[1024];
            int bytesRead = stream.Read(data, 0, data.Length);
            string json = Encoding.UTF8.GetString(data, 0, bytesRead);
            ProcessLandmarks(json);
        }
    }
 
    private void ProcessLandmarks(string json)
    {
        // 解析JSON并更新Avatar
    }
}

3.2 3D服装物理模拟

3.2.1 服装资源准备规范

  1. 使用Marvelous Designer制作基础版型。
  2. 导出为FBX格式,包含以下要求:
    • 网格面数控制在5000-8000三角面;
    • 包含Cloth约束标签;
    • 骨骼绑定采用Heatmap权重。

3.2.2 Unity物理材质配置

// ClothController.cs
using UnityEngine;
 
[RequireComponent(typeof(Cloth))]
public class ClothController : MonoBehaviour
{
    public Transform[] attachmentPoints;
    private Cloth cloth;
 
    void Start()
    {
        cloth = GetComponent<Cloth>();
        ConfigureClothPhysics();
    }
 
    void ConfigureClothPhysics()
    {
        // 基础物理参数
        cloth.bendingStiffness = 0.5f;
        cloth.stretchingStiffness = 0.8f;
        cloth.damping = 0.1f;
        
        // 碰撞设置
        cloth.selfCollision.enabled = true;
        cloth.selfCollision.stiffness = 0.2f;
    }
 
    public void AttachToPoints(Transform[] points)
    {
        // 动态绑定到人体骨骼点
    }
}

3.3 AR试穿界面开发

3.3.1 空间映射实现

// ARSessionManager.cs
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
 
public class ARSessionManager : MonoBehaviour
{
    [SerializeField]
    private ARSession arSession;
 
    void Start()
    {
        ARSessionManager.sessionStateChanged += OnSessionStateChanged;
        arSession.Reset();
    }
 
    private void OnSessionStateChanged(ARSessionStateChangedEventArgs args)
    {
        if (args.state == ARSessionState.SessionTracking)
        {
            EnablePlaneDetection();
        }
    }
 
    private void EnablePlaneDetection()
    {
        ARPlaneManager planeManager = FindObjectOfType<ARPlaneManager>();
        planeManager.enabled = true;
    }
}

3.3.2 交互界面设计

<!-- CanvasSetup.uxml (Unity UI Builder) -->
<VerticalLayout>
    <Button id="switchModelBtn" text="切换服装"/>
    <Slider id="fitSlider" min="0" max="100" value="50"/>
    <Toggle id="physicsToggle" text="物理模拟"/>
</VerticalLayout>

3.4 用户反馈系统集成

3.4.1 本地反馈收集

// FeedbackSystem.cs
using UnityEngine;
using System.IO;
 
public class FeedbackSystem : MonoBehaviour
{
    public void SubmitFeedback(string comment, int rating)
    {
        string logEntry = $"{System.DateTime.Now}: Rating {rating} - {comment}\n";
        File.AppendAllText("feedback.log", logEntry);
    }
 
    public void AnalyzeFeedback()
    {
        // 简单情感分析示例
        string[] lines = File.ReadAllLines("feedback.log");
        int positiveCount = 0;
        foreach (string line in lines)
        {
            if (line.Contains("good") || line.Contains("great"))
                positiveCount++;
        }
        Debug.Log($"Positive Feedback Ratio: {positiveCount / lines.Length}");
    }
}

四、完整系统整合

4.1 主控逻辑流程

// VirtualFittingRoom.cs
using UnityEngine;
 
public class VirtualFittingRoom : MonoBehaviour
{
    [SerializeField] private GameObject[] clothingItems;
    private int currentClothingIndex = 0;
 
    void Start()
    {
        InitializeSubsystems();
        LoadInitialClothing();
    }
 
    void Update()
    {
        HandleInput();
        UpdateClothingPhysics();
    }
 
    private void InitializeSubsystems()
    {
        // 初始化AR、姿态接收、UI等
    }
 
    private void LoadInitialClothing()
    {
        Instantiate(clothingItems[currentClothingIndex], transform);
    }
 
    private void HandleInput()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            SwitchClothing();
        }
    }
 
    private void SwitchClothing()
    {
        Destroy(clothingItems[currentClothingIndex]);
        currentClothingIndex = (currentClothingIndex + 1) % clothingItems.Length;
        LoadInitialClothing();
    }
}

4.2 性能优化策略

  1. 姿态数据降频:每秒处理15帧而非30帧。
  2. LOD系统:根据距离动态调整服装网格精度。
  3. 异步加载:使用Addressables进行资源管理。
  4. 遮挡剔除:启用Unity的Occlusion Culling。

五、部署与测试

5.1 构建配置要点

  • 移动端适配:
    • 设置目标分辨率为1920×1080 ;
    • 启用Multithreaded Rendering ;
    • 设置Graphics API为Vulkan(Android)/Metal(iOS)。
  • Web部署:
    • 使用Unity WebGL构建;
    • 配置WASM内存为512MB;
    • 启用Code Striping。

5.2 测试用例设计

测试类型 测试场景 预期结果
姿态追踪 快速肢体运动 服装跟随延迟 < 200ms
物理模拟 坐下/起身动作 服装褶皱自然无穿透
AR稳定性 不同光照条件 空间锚点持续稳定
多设备兼容性 iOS/Android旗舰机型 帧率稳定在30+ FPS

六、扩展方向与行业应用

6.1 技术升级路径

  1. AI驱动:
    • 集成Stable Diffusion实现服装自动生成;
    • 使用ONNX Runtime优化ML推理。
  2. 交互升级:
    • 添加手势控制(通过MediaPipe Hand模块);
    • 实现语音交互(集成Azure Speech SDK)。

6.2 商业应用场景

  • 电商领域:AR试衣间提升转化率;
  • 影视制作:实时动作捕捉预览;
  • 医疗康复:姿势矫正训练系统。

七、完整项目代码结构

VirtualFittingRoom/
├── Assets/
│   ├── Scripts/          # 所有C#脚本
│   ├── Materials/        # 物理材质配置
│   ├── Models/           # 服装FBX资源
│   ├── Prefabs/          # 预制件集合
│   └── StreamAssets/     # AR配置文件
├── Python/
│   └── pose_server.py    # 姿态检测服务端
└── Docs/
    └── API_Reference.md  # 开发文档

八、总结与展望

本文详细阐述了从人体姿态捕捉到服装物理模拟的完整技术链路,通过MediaPipe+Unity的协同工作实现了具有商业价值的虚拟试衣解决方案。未来随着5G+AI技术的发展,该系统可拓展至:

  • 跨平台数字分身系统;
  • 大规模虚拟时装秀平台;
  • 个性化服装推荐引擎。

开发者可通过优化物理引擎参数、增加布料类型支持、完善用户反馈机制等方式持续提升系统实用性。