分类 未分类 下的文章

官方资料https://www.npmjs.com/package/dotenv
dotenv本质上是一个非常简单的库, 仅仅用来从.env文件中加载环境变量, 其中存储和代码无关的内容或者不能放在代码中的内容 ,尤其是api_key等安全密钥等. .env文件通过.gitignore忽略.
用来替代windows中的set some_var=value和linux中的export some_var=value

运行

很简单的运行方式:

require('dotenv').config()
console.log(process.env) // remove this after you've confirmed it is working

除此之外, 还可以通过命令行运行而不需要加到代码中

 node -r dotenv/config your_script.js

.env文件定义

.env文件的定义方式, 如果值中包括 #, `,\n`转义字符,回车换行等, 需要加双引号, 否则可以使用不加双引号的简写方式.

S3_BUCKET="YOURS3BUCKET"
SECRET_KEY="YOURSECRETKEYGOESHERE"
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
Kh9NV...
...
-----END RSA PRIVATE KEY-----"
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nKh9NV...\n-----END RSA PRIVATE KEY-----\n"
# This is a comment
SECRET_KEY=YOURSECRETKEYGOESHERE # comment
SECRET_HASH="something-with-a-#-hash"

官方协议文档: https://modelcontextprotocol.io/docs
分为数据层data layer和传输层transport layer

data layer

使用 JSONRPC2.0作为通讯协议, 包括生命周期管理和原语.

生命周期管理

MCP是有状态的协议, 所以需要生命周期管理, 目的是客户端和服务器协商彼此支持的能力(原语).

原语 primitives

包括服务器暴露的原语和客户端暴露的原语, 以及跨领域功能原语.

服务器原语包括:

- 工具 Tools 资源 Resources 提示词 Prompts
控制者 大模型 应用 用户
工具 tools

包括 tools/listtools/call
示例:

{
  name: "searchFlights",
  description: "Search for available flights",
  inputSchema: {
    type: "object",
    properties: {
      origin: { type: "string", description: "Departure city" },
      destination: { type: "string", description: "Arrival city" },
      date: { type: "string", format: "date", description: "Travel date" }
    },
    required: ["origin", "destination", "date"]
  }
}

工具调用在必要时通过User Interaction Model用户交互模型让用户确认.

资源 resources

每个资源都有一个唯一的 URI(例如, file:///path/to/document.md ),并声明其 MIME 类型以进行适当的内容处理。
资源支持两种发现模式:

  • 直接资源Direct Resources- 指向特定数据的固定 URI。示例: calendar://events/2024 - 返回 2024 年的日历可用性
  • 资源模板Resource Templates - 带参数的动态 URI,用于灵活查询。如: travel://activities/{city}/{category} - 按城市和类别返回活动, 或者: travel://activities/barcelona/museums - 返回巴塞罗那的所有博物馆
    操作包括: resources/list, resources/templates/list, resources/read, resources/subscribe
    资源模板示例:
    
    {
    "uriTemplate": "weather://forecast/{city}/{date}",
    "name": "weather-forecast",
    "title": "Weather Forecast",
    "description": "Get weather forecast for any city and date",
    "mimeType": "application/json"
    }

{
"uriTemplate": "travel://flights/{origin}/{destination}",
"name": "flight-search",
"title": "Flight Search",
"description": "Search available flights between cities",
"mimeType": "application/json"
}

支持参数补全和用户交互模型.

Prompts 提示系统

提示提供可重用的模板。它们允许 MCP 服务器作者为特定领域提供参数化提示,或展示如何最佳使用 MCP 服务器。
支持方法: prompts/list, prompts/get
示例:

{
  "name": "plan-vacation",
  "title": "Plan a vacation",
  "description": "Guide through vacation planning process",
  "arguments": [
    { "name": "destination", "type": "string", "required": true },
    { "name": "duration", "type": "number", "description": "days" },
    { "name": "budget", "type": "number", "required": false },
    { "name": "interests", "type": "array", "items": { "type": "string" } }
  ]
}
#### 客户端原语包括: 
##### 采样 `sampling/complete`
采样允许服务器通过客户端请求 LLM 补全而不需要重复内建对LLM的调用,从而实现代理式工作流程。这种方法将客户端置于对用户权限和安全措施的完全控制之下。

##### 提取 `elicitation/requestInput`
提取使服务器能够在交互过程中请求特定信息,为服务器按需收集信息提供了一种结构化方式。
提示是结构化的模板,定义了预期的输入和交互模式。它们由用户控制,需要显式调用而非自动触发。提示可以感知上下文,引用可用的资源和工具以创建全面的流程。类似于资源,提示支持参数完成,以帮助用户发现有效的参数值。
支持方法: `prompts/list` 和 `prompts/get`

##### 根 Roots
根允许客户端指定服务器应关注的目录,通过协调机制传达预期范围。主要用作AI操作文件服务.
结构样式:
```json
{
  "uri": "file:///Users/agent/travel-planning",
  "name": "Travel Planning Workspace"
}
日志 logging

跨领域的功能原语 utility primitives

前有1个

  • Tasks 支持延迟结果获取和状态跟踪

transport layer

支持 stdio和treamable HTTP两种传输机制. 使用 HTTP POST 进行客户端到服务器的消息传递,并可选使用 Server-Sent Events 实现流式功能. 该传输支持远程服务器通信,并支持标准 HTTP 认证方法,包括授权令牌、API 密钥和自定义头信息。MCP 推荐使用 OAuth 获取认证令牌。

MCP协议使用JSONRPC作为底层数据层的传输协议. 这是一个及其简单明了的协议, 官方定义在这儿: https://www.jsonrpc.org/specification

简单说明:

  • JSONRPC是客户端向服务器发起一个请求Request, 服务器返回一个响应Response.
  • 客户端发起的请求有id时, 服务器必须响应并带上id, 如果客户端发起的请求没有id, 则这个请求是一个"通知", 服务器不需要响应.
  • 服务器的响应中必须有id, 如果这个id是null, 则说明客户端给的id有问题
    request格式:
    {
    "jsonrpc": "2.0",  // 必选, 值必须是"2.0"
    "method": "subtract", // 必选, 值为string
    "params": [42, 23],  // 可选, 按具体method的要求
    "id": 1 // 要返回值时必选, 不要返回值是必须省略
    }

    response 成功时格式:

    {
    "jsonrpc": "2.0", // 必选, 值必须是"2.0"
    "result": 19, // 成功时必须有, 失败时必须没有
    "id": 1 // 必须有, 与客户端request中一致
    }

    response 失败时格式

    {
    "jsonrpc": "2.0", 
    "error": { // 失败时必须有, 成功时必须没有
      "code": -32601, // 必选, 为整数. 其中从-32768 到-32000 范围内的错误代码被保留用于预定义错误
      "message": "Method not found" // 必选, 为string, 一句话描述错误.
    }, 
    "id": "1" // 必选, 解析不了client发来的id时候返回null
    }

    更多示例请看官方文档. https://www.jsonrpc.org/specification

一个阳光明媚的清晨,小猫从睡梦中醒了过来,迷迷糊糊的睁开了眼睛。忽然他发现一只蝴蝶停在房间的墙上。蝴蝶长得很漂亮,身上闪着五颜六色的光。
小猫说:“蝴蝶蝴蝶,你真漂亮!你是从哪里来的呀?”
蝴蝶说:“我是从那边的大森林飞过来的。”
小猫说:“我知道,那是古代的魔法大森林!你一定会魔法吧?”
蝴蝶说:“那边有上千年的魔法还有我刚学的新魔法你要不要一起试试呀?”
小猫说:“好呀好呀那我们一起去大森林玩吧!”
蝴蝶说:“那好我带你去。”蝴蝶在空中转了一个八字,身体变大了数倍,让小猫骑在他的背上,一下就飞到了空中。
时间好像倒流了数亿年,他们来到了远古时代的大森林。这里长着各种小猫没有见过的奇花异草。有高耸入云的大树,还有长得像蚂蚁一样大小的小鸟。
蝴蝶看着小鸟,看好像有点害怕。蝴蝶说:“不用害怕这里的日常就是这样的。”
小猫说:“你带我参观一下吧!”
小猫仔细的瞧了瞧森林里的植物和动物,蝴蝶一边飞一边给他介绍这里真的很漂亮又好神奇,很快一天就过去了。
天很快就黑了。“我们回去吧!”说完小猫和蝴蝶就在一处大榕树下告别了。

看了最新一期的罗永浩的十字路口与刘谦的访谈,有感几点:
1、刘谦说努力没那么重要,运气占90%。他说出这个我就相信他说的话都是真的。与我运势学相通。很巧,这和马斯克说的努力10次成功一次的比例概率一模一样。
2、刘谦就此得出第2点结论:享受创造的过程而不是追求成功的结果。因为成功的结果可能性在10%以内,甚至现实往往还要更低得多。并且把这一点放在了孩子的教育上。与此同时他又说了两个例外,一个是不善交际的他做街头魔术必须要与各色人等交谈,另一个是直播带货,这两天对他来说言语方面成长很多。
3、外表和包装真的非常重要,尤其对一个刚刚起步的个体来说。刘谦说他花1万多人民币买套西装,在网站不发达的时候自己做网站还包装出好几个虚拟工作人员来伪装自己的一人公司。而且这个习惯一直持续到现在,他的外在形象包括香水发型衣服全部要自己操办不放心交给别人。这让我想到迈克尔杰克逊、乔布斯都是极其注重外观的。我看不上的那些 html css动画却真的是产品非常重要的一部分。
4、刘谦反复讲了好多次让他的观众感受哇哦一刻,甚至这一刻可以在他的一生中反复跟别人去诉说,变成一个人生的重要经历。然后魔术师为了这一刻苦练多年、准备良久。不能给别人留下这一刻就绝不出手。我想这一刻就是人生的幸福体验。人生留在脑子里值得回味的幸福体验其实很少,无论做任何一个职业,如果能给别人留下一刻的幸福体验并且记住一生那其实是非常了不起、非常有意义的事情。我觉得这可能才是艺术的定义:给别人留下铭刻一生的体验。一个产品如果能做到这一点那他就是个艺术品。

微信小程序云函数超时的问题。微信小程序,云函数有几个超时的问题。其中1个是访问cloud api的时候,这个是可以在云函数端cloud.init的时候设置。但是还有1个调用云函数超时的问题。每次调用函数运行的最长时间不能超过3秒钟。如果超过,则会返回超时。 1般情况下,只有几100毫秒就可以完成云函数的调用,但是如果调用第3方api的时候,就可能因为第3方api处理时间过长导致超时。
让ai给我找了很多办法去延长这个超市时间,但似乎都无法延长。最后只有不使用await调用,直接进行返回,才能避免。

菜鸟的教程不错,很适合做快速入门参考。https://www.runoob.com/r/r-tutorial.html
首先不要把R语言看成正常的通用编程语言,像C/C++/Java/Js那种,而是看做特定用途的语言。虽然不像是HTML/CSS这两种语言形态那么极端。可以把R语言看成是升级版的Excel函数库,当然不是一星半点的升级了。不过,你想象R语言在操作数据表有一些语言层次的支持和天然的优势就对了。
整体语法上和非严格模式的JavaScript比较相似,在此基础上讲最重大的几个区别:

  • 与多数语言不同,.是合法的变量名字符,访问一个对象的子元素要用$
  • 与多数语言不同,安装包install.packages()、修改工作目录getwd() setwd()全在语言内,就好像本身是系统脚本bat或者bash
    与Js相似又有区别的点:
  • =可以用来赋值,但这个是后来才加的,赋值符号的原住民是<-->,是的,还能向右赋值。
  • 语句尾部不用任何符号
  • 打印是 print()
  • 函数形参接受类似python的形参名=形参值的方式

用管理员打开cmd, 运行:

# 输入
net stop MariaDB
# 输出
MariaDB 服务正在停止...
MariaDB 服务已成功停止。

手动运行mysqld服务, 打印输出并跳过权限表的检查

mysqld.exe --console --skip-grant-tables

新开一个cmd,使用mysql无密码登录:

mysql -u root

进入mysql终端, 重置密码:

FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password';

切回mysqld的管理员cmd窗口, Ctrl+C结束mysqld运行, 启动mysqld服务:

net start MariaDB

测试新密码登录:

mysql -u root -p

目前来看云函数是不行的,但是函数式云托管可以。sse和websocket都需要运行在云托管或者函数式云托管中。
https://docs.cloudbase.net/cbrf/intro
似乎函数式云托管支持sse也是为了大模型:
https://docs.cloudbase.net/cbrf/example#%E4%BD%BF%E7%94%A8-server-sent-event-%E6%8E%A8%E9%80%81%E6%B6%88%E6%81%AF
官方也给出了与云托管和云函数的对比
https://docs.cloudbase.net/cbrf/vs
但是,函数型云托管的sse和ws实例都是通过context传入的。如const sse = context.sse(), const ws=contex.ws, 对于第三方库里已经封装了sse方法的(如mcp官方库 @modelcontextprotocol/sdk), 似乎就只有去修改官方库源文件才能做到兼容吧? 这样多少有些得不偿失的感觉. 此时,似乎更应该去使用正常的基于容器的云托管.
价格问题. 有两个官方文档 第一个https://cloud.tencent.com/document/product/876/113602 是对云托管的计费, 第二个 https://cloud.tencent.com/document/product/876/120342 是云托管与标准计费项的换算.
那么最重要的一点就是云托管的容器实例是持续运行还是调用以后就下线的. 从 https://docs.cloudbase.net/run/develop/developing-guide 这儿看: 服务必须是无状态服务,不能依赖永久性本地状态。这是为了能够进行水平的自动扩缩容。, 应该是调用后就下线的. 另外在 概述中也提到, 实例数量会根据请求量自动调整,无请求时可缩容到 0,不产生费用。, 这点应该可以大大降低实际费用.

AI 创作中的版权难题
在 AI 的创作中,往往会遇到版权问题。因为 AI 是模拟了一个人物,如果这个人物是一个比较著名的人物,那么他的形象、他的声音都会存在版权难题。这也许就是为什么很少公开的模拟某一个具体的现在存在的人物形象。即便是虚拟的人物,由于这个虚拟人物的归属与某一个特定的公司,那也存在版权的问题。要规避这个问题,可能只能去创作历史人物,这个人物你如果有一些现代的演绎,比如说在电影、电视剧中曾经被人扮演过,那么他就会形成一个认知,这是这个人物的形象,或者他的声音应该是什么样子的。那假如说要规避它的这个已经认知的声音和形象,就需要重新去配音和重新去生成形象。按照现在的 AI 绘画的水平,它的形象的生成很难一次性就生成自己想要的那种样子,就会出现反复多次的修改的情况。会浪费必要多的时间和精力,当然这已经比你请人去从头开始绘画好很多了,声音也是如此。如何才能仿照书不同人的声音,老年人的小孩、女人的声音,正好又让他去符合自己心目中的历史形象,是一个很大的问题。这里也估计有反复尝试,试错的过程,会使一个形象的生成,包括他的头像、声音等等都需要花费比较巨大的时间。这和简单的生成一个人物的背景提示词相比,可能就有比较大的时间成本上的差异。

AI编程到今天,应该用了已经快一年时间了。慢慢的逐渐考虑它用于比较复杂的项目。
什么是复杂的项目?

  • 人工智能要理解定制的框架、开发库,而不是公开的那些。由于定制的框架和开发库缺乏公开文档,在人工智能的训练过程中,肯定不会有任何相关的资料做训练。如何能正确的使用这些框架和开发库,这是第1个复杂所在。
  • 人工智能要理解ui界面的设计,并且精确地按照涉及生成软件界面。正常情况下,ui界面一定是使用画图工具来做的。但是人工智能做ui界面,首先就遇到了内容一致性问题和将文字置于图像上的问题无法完美解决。这是第2个复杂所在。
  • 人工智能对文档中缺乏的部分,会通过幻觉自作主张的进行脑补。并且以脑补的内容作为基础填充代码的其他部分。如果没有早期发觉,它可能会污染项目的很多代码文件,导致代码最终难以修复。这是第3个复杂所在。
  • 一旦项目中的文档代码过多的时候,实现一个功能就需要引入非常多的内容作为参考才能开发。在人工智能上下文token有限的情况下,可能会导致人工智能难以正确回答。并且给人工智能输入过长的上下文会导致其注意力不集中,最终并不会完全遵循上下文的内容,甚至会遗漏很多部分。
    尝试去实现复杂的项目,就要解决上述的问题。
  • 对于定制的框架和开发库,可以先让人工智能去阅读整个开发库,去生成对应的开发文档。后面通过上下文带入开发文档,方便开发。还可以先写一个框架代码,提前将定制的库引入,这样人工智能会先阅读框架代码。并去顺着框架代码阅读引入的库。但对于api调用这种情况,还是要从文档入手。或者先让人工智能写一个api调用的库,再去写其他代码。
  • 对于现阶段人工智能还不能很好地生成图形ui设计的情况下,可以先让他设计文字形式的ui图。在文字图中标注ui元素的长宽。
  • 对于幻觉脑补,则需要对人工智能生成的代码进行立即测试,及早发现问题,避免扩散。避免生成不能测试的代码。现在还好的是,多数ai编程工具可以回退。
  • 对于引用上下文过多的情况,可以先进行模块化划分。已经划分模块的,可以将较大的模块划分成更小的模块。在每个模块中引用相对较少的上下文,并且在当前模块中实现一个较小的接口代码,其他模块引用这个接口代码,避免大模型每次都需要阅读模块代码的所有细节。
    总的原则是要把复杂的项目拆分成大模型可以很好遵循的小项目,小项目的标准是引用的上下文要少,实现的代码要少,少到大模型可以很好遵循为止。当然目前这个度还不是特别好把握。

应该坚持用AI编程吗?
是的。我发现一个最大的好处,尤其是对于独立开发者来说,AI编程总会用一些让你从未见过的、令人惊喜的语言特性或者函数。因为一个人的编程习惯容易固化,越早学习一种编程语言,越习惯用这种语言的早期风格。而如今编程语言的进化日新月异,新的语言版本带来了新的特性,而自己由于对旧模式得心应手,也就不会在关注和使用。对于第三方库来说更加明显,一般都是到了某个函数需要弃用、或者弃用以后才会去想办法找新的替代,也就是不出问题就不会去查文档的。比如我看到好多人写JS仍然喜欢用callback回调地狱处理异步函数, 各种括号真得深入地狱十八层了,也没有使用promise风格;我自己一直很喜欢使用promise,却不知道css标准早已经支持了变量var和计算calc,以为这个还是其他第三方CSS扩展如SCSS/LESS才有的功能(因为了解SCSS和LESS太早了);也是AI帮我知道了页面栈获取函数getCurrentPages其实有超强的能力,因为栈中页面的所有函数包括setData都可以调用而且起作用(即使页面是hide状态)。新的语言特性让代码变得清爽简洁,自然也能节约大量时间,这是从AI编程可以学到的。
另外, AI处理页面UI确实速度又快又好, 不过有些情况AI会考虑不到, 如微信小程序自动注入一些CSS, 这些需要在和AI的配合中逐步写入它的规则中。

看了把科学带回家的一篇文章名字叫:为什么在沙发上睡着很容易,在床上睡着很难。我有一个洞察是:睡不着的原因并不是脑袋里想事情,而是对未知的焦虑。相反来说,能睡着的原因是略带新鲜的完全掌控感。
人的大脑几乎是无时无刻都在想事情的,很少情况会脑袋空空如也地发呆。即便对于躺倒就睡的人在躺倒的前一刻,至少也想着要盖被子,枕枕头。而现代人的生活一般都是连续的。今天应有未做完的事情,需要明天继续做。明天怎么完成这个事情的方法,今天还没有想出来。因为工作是充斥了整个白天一整天的最主要的事物,所以到了晚上睡觉前,那些没有完成的事情就会在脑海里翻转出来,寻找解决方案。但无论你找得到方案还是找不到方案,都需要第2天白天去实施,没法躺在床上尝试的。这就意味着你无法检验这个方案到底是否可行。所以最终不管你找不找得到方案,都会焦虑的睡不着。因此归根结底,你在睡觉前脑子里想的这个事情是无法获得完全掌控感的。
所以这里的第1个洞察就是要获得完全掌控感。
那么为什么要略带新鲜呢?如果在思考的事情非常乏味,很容易丢失注意力,而转回到白天的工作上去。如果思考的事情。非常新鲜有趣,会导致自己忍不住要持续的想下去,也会睡不着。
这里就有第2个洞察,略带新鲜,目的是牵引注意力在完全掌控感之中。同时又不让注意力沉浸在新鲜感中。
由于新鲜是相对的。所以同一种方法可能对不同的人有不同的适用。

由于小智使用了opus编解码音频,而在xiaozhi-esp32-server中,使用了libopus.js进行音频解码。
libopus.js的代码经过压缩,仍然有825K。由于微信小程序不支持opus,以前我试图用AI将libopus改为支持微信小程序环境,然而失败了。以前以为是代码过大的原因,今天才发现,除此之外还有libopus.js使用了asm.js的原因。
asm.js在2013年由mozilla在firefox中提出并实现,其他浏览器也有实现,但似乎支持度一般,也不是正式的JS标准。asm.js以"use asm"开头,后面使用js的子集代码,去掉了js动态语言部分,加载时会先编译再运行来提高运行速度。
其他浏览器不在强力支持的原因是,asm.js后来在2015年演化为W3C标准制定的WebAssembly, 提出了浏览器中运行编译后二进制代码的方式和二进制.wasm文件。由于wasm和js同等地位且wasm可以被js调用,并且wasm可以由多种语言编译而来,得到了众多浏览器和node.js的广泛支持,所以asm.js逐渐被淘汰了,现在浏览器中写asm.js代码,能用但是会提示已经被deprecated了。
不同语言编译为wasm的编译器不太一样,C/C++最著名的是emscripten, rust是wasm-pack,其他语言也有,但是似乎不如这两个这么流行。可能是C/C++/Rust本身就是最快的几个语言了,其他语言也许编译后的效率比不上。emscripten历史比较悠久,在asm.js还流行的时候就可以把C/C++编译为asm.js代码了.

如果你曾经把小程序的开发切换为多端应用的开发方式,那么即使你切换回普通小程序的开发方式,仍然会出现多端应用的某些标记已经在你的项目中生成了。主要增加了project.miniapp.json文件, 在project.config.json文件中增加了"projectArchitecture": "multiPlatform"配置项。
在小程序打包上传的时候会增加一个分包,名字叫做 /donutAuthorize__/,可以在详情-基本信息-上次上传/预览中看到。
然而你搜索遍整个项目都不会找到donut的一点点信息的,也不会提醒你审核问题。然而你在发布后审核会以你提前获取了用户的昵称、手机号码、头像为理由驳回你的申请。我提交了三次,其中有一个比较负责的审核给我截了图,截图中显示我的小程序获取你在当前小程序的登录态信息。下面有个说明:

说明
将移动应用和多端应用绑定即可消除该水印;如已绑定移动应用,需在开发者工具中切摸到小程序模式重新提交小程序代码生成新版本方可消除该水印
这里才有一点点多端应用作祟的线索。

下面是多端问答机器人的回复, 解决了问题. 我找了小程序审核和小程序审核客服都没有能正确回答出来.

我不想用多端模式开发小程序, 向回到单纯的小程序开发模式, 该怎么办

多端问答机器人
若需从多端应用模式恢复为普通小程序开发模式,请按以下步骤操作:

删除配置文件:

删除项目根目录下的 project.miniapp.json 文件(多端应用专用配置)
修改工程配置:

打开 project.config.json 文件
移除 "projectArchitecture": "multiPlatform" 配置项
完成上述操作后,重新打开项目即可恢复为普通小程序项目。该操作不会影响原有小程序功能,但会丢失多端应用特有的配置(如构建模式、多端API等)。

删除app.json中的"miniApp": { "useAuthorizePage": true }配置

注意事项:

操作前建议备份项目文件
若项目中使用过多端专用API,恢复后需自行处理兼容性问题
再次切换回多端模式需重新绑定小程序