Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

前阵子一个manus在目前的所谓人工智能圈子里甚至普通人视野里都很火了,宣称是什么中国的下一个deepseek时刻,首先deepseek是经过了v1,v2等一系列版本的迭代之后,并且一直是在技术上非常花功夫的,有种宝剑锋从磨砺出的感觉,而这个manus听着更像是个蹭热度的
这不没出多久有个openmanus宣称用了三小时做了个开源的复刻版,那么我们就来简单体验下,从概念上来说吧,有点类似于做了个mcp的规划和整合调用
我个人理解好像没有到改变世界的程度
首先呢我们先来安装下
可以使用conda,也可以使用uv,以conda举例,先建个环境

1
2
conda create -n open_manus python=3.12
conda activate open_manus

然后来clone下代码仓库

1
2
git clone https://github.com/mannaandpoem/OpenManus.git
cd OpenManus

接着再安装下依赖

1
pip install -r requirements.txt

这里可以借助下源替换加速,临时使用可以这样子 pip install -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple some-package , 这里需要安装蛮久的,可能也说明了这是个依赖于很多现成库的工具

第二阶段配置

配置其实也是常规的,依赖于大模型,那么要不就是自己部署提供api,要不就是去火山引擎或者其他大模型api提供商搞个api(免费额度用完要自己付费的)

1
cp config/config.example.toml config/config.toml

这一步其实跟之前使用chatbox连接火山的配置类似
因为像国外很多都还是openai的接口服务,这边就需要改用成国内可用的

1
2
3
4
5
6
[llm]
model = "deepseek-r1-250120" # The LLM model to use
base_url = "https://ark.cn-beijing.volces.com/api/v3" # API endpoint URL
api_key = "xxxxxxxxxxxxxxxxxx" # Your API key
max_tokens = 8192 # Maximum number of tokens in the response
temperature = 0.0

模型可以用deepseek-r1,不过要注意是什么时间版本的,否则也会访问不到
然后我们就可以运行

1
python main.py

来运行openmanus,我们简单问个问题

1
明天杭州的天气怎么样,给出个穿衣指南

看下结果

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
python main.py
INFO [browser_use] BrowserUse logging setup complete with level info
INFO [root] Anonymized telemetry enabled. See https://docs.browser-use.com/development/telemetry for more information.
Enter your prompt: 帮我看下明天杭州的天气,并且生成穿衣指南
2025-04-20 20:40:14.721 | WARNING | __main__:main:16 - Processing your request...
2025-04-20 20:40:14.722 | INFO | app.agent.base:run:140 - Executing step 1/20
2025-04-20 20:40:33.488 | INFO | app.llm:update_token_count:250 - Token usage: Input=2165, Completion=658, Cumulative Input=2165, Cumulative Completion=658, Total=2823, Cumulative Total=2823
2025-04-20 20:40:33.489 | INFO | app.agent.toolcall:think:81 - ✨ Manus's thoughts:


2025-04-20 20:40:33.489 | INFO | app.agent.toolcall:think:82 - 🛠️ Manus selected 1 tools to use
2025-04-20 20:40:33.489 | INFO | app.agent.toolcall:think:86 - 🧰 Tools being prepared: ['browser_use']
2025-04-20 20:40:33.489 | INFO | app.agent.toolcall:think:89 - 🔧 Tool arguments: {
"action": "web_search",
"query": "杭州明天天气预报"
}
2025-04-20 20:40:33.490 | INFO | app.agent.toolcall:execute_tool:180 - 🔧 Activating tool: 'browser_use'...
ERROR [browser] Failed to initialize Playwright browser: BrowserType.launch: Executable doesn't exist at /Users/username/Library/Caches/ms-playwright/chromium-1161/chrome-mac/Chromium.app/Contents/MacOS/Chromium
╔════════════════════════════════════════════════════════════╗
║ Looks like Playwright was just installed or updated. ║
║ Please run the following command to download new browsers: ║
║ ║
║ playwright install ║
║ ║
║ <3 Playwright Team ║
╚════════════════════════════════════════════════════════════╝
2025-04-20 20:40:34.896 | INFO | app.agent.toolcall:act:150 - 🎯 Tool 'browser_use' completed its mission! Result: Observed output of cmd `browser_use` executed:
Error: Browser action 'web_search' failed: BrowserType.launch: Executable doesn't exist at /Users/username/Library/Caches/ms-playwright/chromium-1161/chrome-mac/Chromium.app/Contents/MacOS/Chromium
╔════════════════════════════════════════════════════════════╗
║ Looks like Playwright was just installed or updated. ║
║ Please run the following command to download new browsers: ║
║ ║
║ playwright install ║
║ ║
║ <3 Playwright Team ║
╚════════════════════════════════════════════════════════════╝
2025-04-20 20:40:34.896 | INFO | app.agent.base:run:140 - Executing step 2/20
ERROR [browser] Failed to initialize Playwright browser: BrowserType.launch: Executable doesn't exist at /Users/username/Library/Caches/ms-playwright/chromium-1161/chrome-mac/Chromium.app/Contents/MacOS/Chromium
╔════════════════════════════════════════════════════════════╗
║ Looks like Playwright was just installed or updated. ║
║ Please run the following command to download new browsers: ║
║ ║
║ playwright install ║
║ ║
║ <3 Playwright Team ║
╚════════════════════════════════════════════════════════════╝
WARNING [browser] Page load failed, continuing...
ERROR [browser] Failed to initialize Playwright browser: BrowserType.launch: Executable doesn't exist at /Users/username/Library/Caches/ms-playwright/chromium-1161/chrome-mac/Chromium.app/Contents/MacOS/Chromium
╔════════════════════════════════════════════════════════════╗
║ Looks like Playwright was just installed or updated. ║
║ Please run the following command to download new browsers: ║
║ ║
║ playwright install ║
║ ║
║ <3 Playwright Team ║
╚════════════════════════════════════════════════════════════╝

根据这个返回可以看到它做了些啥,主要是规划步骤和选择调用的工具,相对来说没有特别的,playwright我就不去搞了,浏览器那套

arthas是阿里开源的一个非常好用的java诊断工具,提供了很多很好用的命令,这里讲一个最近使用到的
就是将arthas挂载上我们的springboot应用,然后调用其中的方法,这样能够在如果没加日志已经看不到函数返回时更方便的排查问题
首先举个例子,我们有个Controller
它的一个query方法是这样的

1
2
3
4
5
@RequestMapping(value = "/query", method = RequestMethod.GET)
@ResponseBody
public String query() {
return demoService.queryName("1");
}

而在这个demoService中它的实现是这样

1
2
3
4
5
6
7
public String queryName(String no) {
if ("1".equals(no)) {
return "no1";
} else {
return "no2";
}
}

假如现在Controller这的这个方法有点问题,那么我想确认下是不是demoService这个方法的实现有问题,或者说确定下它的返回值是否符合预期
那么我们就可以在应用启动后,运行arthas,找到这个应用的进程,进行挂载
然后执行

1
vmtool --action getInstances --className com.nicksxs.spbdemo.service.DemoServiceImpl --express 'instances[0].queryName("1")'

先介绍下这个vmtool命令
主要来说 vmtool 可以利用JVMTI接口,实现查询内存对象,强制 GC 等功能。
例如官方示例里的,我想把内存里的string对象捞一些出来看看存的是啥

1
vmtool --action getInstances --className java.lang.String --limit 10

就可以这样,首先这个action就是指定要做的操作,支持的action 还包括

1
2
forceGc
interruptThread

等,那么对于 getInstances 就是从内存里捞出这个类的对象,然后是后面一部分
--express 就是执行表达式,这里的表达式,
instances[0].queryName("1") 其中 instances 就是前面从内存中获取的对象数组,因为这些是对象的非静态方法,那就需要从其中取一个来执行我们的方法
另外假如我们的场景里需要对比如返回结果做个json序列化
我们可以这样

1
vmtool --action getInstances --className com.nicksxs.spbdemo.service.DemoServiceImpl --express '@com.alibaba.fastjson.JSON@toJSONString(instances[0].queryName("1"))'

这里为什么类开头跟方法开头要用 @, 是因为对于类和静态方法的调用规则是这样,还有如果代码比较多,有可能默认的类加载器中没有加载这个JSON类,那么就需要在参数中加上指定的classloader,
可以用sc命令来查找我们的目标类的类加载器,一般来说如果目标类是我们核心业务的,大概率也会有JSON这个类

1
sc -d com.nicksxs.spbdemo.service.DemoServiceImpl

然后在上面命令中加上sc结果中的 classLoaderHash 的值,

1
vmtool --action getInstances -c 18b4aac2 --className com.nicksxs.spbdemo.service.DemoServiceImpl --express '@com.alibaba.fastjson.JSON@toJSONString(instances[0].queryName("1"))'

这样就能正常执行了

之前发现Termux在安卓手机中是个比较厉害的神器,就相当于一个随身携带的小型服务器,伴随着现在手机性能的逐渐强大,有些手机可能已经比很多个人用的云服务器还要强大很多,只是有着散热和电量的限制,但是充当一下临时的使用还是很不错的
记得之前提过,在用rustdesk的时候,如果被连端是Mac,并且被连端进入锁屏了,可能需要ssh连上去执行个唤醒命令,正好最近有需求要偶尔从手机连上家里的Mac,从而引发的一个问题是比如我经常用Termux来执行ssh命令,那么理论上我直接从shell的history就可以找到执行过的ssh命令,也就不用经常记对应的ip啥的,但是试用了下发现不行,一开始搜了下以为是没有设置历史存储的大小,可能默认是0,那么需要通过配置来设置

1
2
HISTSIZE=1000
HISTFILESIZE=2000

比如设置1000个命令大小,只是在Termux里不是这个原因,而是在于shell去保存历史的时机,安卓手机在退出应用或者切换应用程序都没法记录这个执行历史,而是需要在Termux中手动地用exit命令退出,才会记录下history历史,
当然也有人在Termux的issue上提到了,能不能捕捉安卓的事件来执行这个exit,否则这个exit有点难记得,相对来说也不方便了很多,容易遗忘,只是这个issue也被关掉了,看看后面会不会优化吧

因为上次那个问题,所以打算把图库迁移到靠谱一些的cloudflare上,这里用到了rclone这个很强大的工具

在开始迁移前,先做一下准备

  1. 分别在腾讯云和 Cloudflare 平台申请 Access Key 和 Secret Key
  2. 安装 rclone 工具(可从 rclone 官网 下载)

配置远程存储

配置步骤

  1. 打开终端,输入 rclone config 开始远程存储配置
  2. n 创建新的远程存储

配置腾讯云 COS

  1. 输入远程存储名称,例如 cos
  2. 选择存储类型,选择 Amazon S3 兼容模式(选项编号可能因 rclone 版本而异)
  3. 选择服务提供商为腾讯云 COS
  4. 输入您的 access_key_idsecret_access_key(从腾讯云控制台获取)
  5. 选择相应的端点 API(根据您的存储桶所在地区选择北京或上海等)
  6. 配置访问权限:可以选择仅资源所有者拥有完全访问权限,或根据您的安全需求选择其他选项
  7. 选择存储类型(通常选择标准存储)
  8. 确认配置

配置 Cloudflare R2

  1. 再次输入 n 创建新的远程存储
  2. 输入远程存储名称,例如 r2
  3. 同样选择 Amazon S3 兼容模式
  4. 选择服务提供商为 Cloudflare R2
  5. 输入您的 access_key_idsecret_access_key(从 Cloudflare 控制台获取)
  6. 输入 R2 的端点 URL(通常格式为 https://<account_id>.r2.cloudflarestorage.com
  7. 配置访问权限
  8. 选择存储类型
  9. 确认配置

执行迁移操作

完成配置后,使用以下命令执行迁移:

1
rclone copy cos:mystore-xxxxxxx/img/ r2:img/ --progress

上述命令将把腾讯云 COS 中 mystore-xxxxxxx 存储桶下的 img 目录中的所有文件复制到 Cloudflare R2 的 img 存储桶中。添加的 --progress 参数可以显示迁移进度。

高级选项

为了获得更好的迁移体验,您可以考虑以下高级选项:

  • 使用 --transfers=N 参数设置并行传输数量,加快迁移速度
  • 使用 --checkers=N 参数设置并行检查数量
  • 使用 --dry-run 参数测试迁移过程而不实际复制文件
  • 使用 --log-file=FILE 参数将迁移日志保存到文件中

例如:

1
rclone copy cos:mystore-xxxxxxx/img/ r2:img/ --progress --transfers=4 --checkers=8 --stats=10s

验证迁移结果

迁移完成后,可以使用以下命令验证两边的文件是否一致:

1
rclone check cos:mystore-xxxxxxx/img/ r2:img/ --one-way

结语

通过 rclone 这一强大工具,可以轻松实现云存储服务之间的数据迁移。Cloudflare R2 提供了稳定可靠的对象存储服务,同时其无出站流量费用的特性也使其成为图库存储的理想选择。

上周四,突然接到腾讯云的电话,当然不是叫我去面试的,是说我账户欠费了,而且一下欠了二十多,因为这个账户我除了包年包月的我都会及时续费,剩下的就是一个放我博客图片的cos对象存储,本来可能一天就几分钱,一年充个十块钱都足够用了,突然一天就欠了二十多还是引起了我的警觉,去看了下说是什么外网下行流量费,我想着怎么又有这么个收费名目了,腾讯云给我的感觉就是一直巧立名目,或者增加收费项,后面也问了客服,说是我开的是公有读私有写,而且允许空refer访问(这个我记得是改过的,不知道为啥现在变成了空refer),也挺奇怪的,这种page托管的博客,不都是只能公有读么,私有读的话我还放啥图片,除非全都走服务端中转。
唯一一个优点是总算有个日志,结果看了下是江苏泰顺一哥们一直在换着ip刷,用的还是固定的okhttp客户端,这里想放个图,但是这个优点也被后面的缺点给淹没了,因为腾讯云不支持按访问客户端和ip段设置黑名单,简直离谱,都立了这个名目收费了,对应的功能还不行,都能怀疑是故意漏个口子让刷
可能暂时就不能放出来图片了,主要是也没精力搞什么服务端加密,打算迁到r2或者其他方式了,如果有大佬对这方面有经验又碰巧看到了这篇文章,希望能给下指导。
还有这位用了江苏泰顺ip(说不定是肉鸡)的哥们,是有啥想不开的呢

0%