PVE的备份和恢复
进入pve管理后台,在各虚拟机的备份选项点击备份
备份文件路径是Var/lib/vz/dump,下载到其他地方保持
需要恢复时将备份文件上传到Var/lib/vz/dump,在存储 local里点击对应的备份文件进行还原,然后启动虚拟机
!!!如果启动虚拟机时提示找不到iso镜像,找到硬件选项,编辑CD/DVD驱动器重新选择一下iso镜像文件
pve直通amd核显没法玩
直接装fedora,然后用fedora的虚拟机装pve
很多时候逆向得到的api只能进行文本对话,不能实现最新的ai特性或者协议。比如function call功能 MCP协议 谷歌最新的a2a协议
我经过实践和尝试,提炼了一套可行的思路和代码,使得逆向api一样可以支持最新的ai相关的特性或协议(目前仅仅尝试了function call和mcp,a2a还需要了解)
是llm的具体能力,专注于单个外部工具的调用生成
一种更上层的宏观的系统设计,通常包含多个function call
打个比方,function call是锤子,剪刀等工具,而Mcp就是说明书之类的东西,指导如何用锤子剪刀等工具制造东西
MCP负责决定在什么时候、为什么以及如何组合使用这些“动作”(包括Function Calling、内部思考、信息检索等)来达成最终目标
fc(function call简称)或者Mcp说通俗点就是,llm根据tools参数和上下文判断要不要从上下文中提取参数执行fc或者Mcp.
不管是fc还是Mcp,最终的执行都不是说ai做的,而是ai返回一个结构化(通常是JSON格式)的指令,然后客户端或者别的什么端进行运算.而ai恰好就可以通过**prompt(提示词)**做到这种效果。
因为我们的思路时,在中转或者2api的服务端先过滤判断一次.
如果需要fc或者mcp,通过另外一轮ai对话提炼参数,把返回的参数加入之前的ai对话中,返回进行fc或者Mcp的运算结果.
接收到运算结果后得把结果重新编排并再进行一次对话,添加一个简单的提示词—–比如:根据上下文回答问题
大致思路流程如图
需要一个question变量存储用户的问题,一个标志变量tools_use表示是用过了工具
是否需要使用工具我是通过提示词让ai不需要使用工具的时候就输出no
1 | # 我的判断是否需要使用工具的提示词 |
1 | tools_use = False |
我也写了一个粗略的提示词想要达成这种效果,但由于我的提示词功力不够以及逆向的模型过于垃圾,导致效果不理想
这样做了以后就可以让逆向api支持mcp协议了
经过openwebui几个简单的工具测试可以达成效果
总结一下,MCP并不是什么困难的东西,只不过批了一层外衣,MCP的模拟过程实质还是用提示词的使用,只要了解了MCP过程中的api返回值接受值的格式就可以轻松地给任意模型加上MCP
未来的llm发展我猜测为两个方向
融合和外挂
就是MOE模型里进一步增加从对话中提取参数结构化输出的能力
就是主模型增强关于是否需要MCP的判断能力,需要的话交给一个极致轻量的次生模型提取参数并结构化输出。由于次生模型只需要提取参数结构化输出,是可以做到轻量且高效准确的,主模型就可以完全抛弃这部分能力,增强其他能力
下一步了解下谷歌的a2a协议
其他X86多网口设备均可以参考
PVE做底层,其他全部用虚拟机解决
直通核显屡次尝试失败,要么开始就不能用,要么用一会就不行了
要么直通成功,没问题了,但是测试虚拟机里安装rocm,无法使用780m核显,且vram占用一直为0
PVE直通核显失败
于是我用fedora做实体机,然后虚拟机里运行PVE
需要gpu的服务都放fedora实体机上
不需要的都放虚拟机里的PVE,这样即使重装也只需要恢复使用gpu的服务
我需要使用gpu的服务有comfyui, 影视(jellyfin或者emby等选一个,其实用的也不多,基本上看alist就行了)
必须双网口及以上才行
1 | # 我的两个网口分别是 enp2s0 enp3s0 使用enp2s0作为网桥 切换到root设置更方便 |
使用fedora的libvirt创建PVE虚拟机
1 | dnf install @virtualization |
可以使用virt-manager以gui方式创建虚拟机
网络源选桥接设备 设备名称填网桥名称
直通需要的设备
pci设备直通到PVE虚拟机后,无法再直通到PVE下的虚拟机,因为PVE无法开启iommu
但我要直通的pci设备只有m2转sata的转接卡
只需要把它直通给PVE就行了
然后通过scsi
把硬盘块直通给虚拟机就行
1 | scsi1: /dev/sdb,cache=directsync,discard=on,iothread=1 |
至此,all in one完成,后续需要加服务,不需要gpu添加到虚拟机PVE
需要GPU的直接添加到宿主机,把宿主机服务的部署整理成脚本,重置后一键恢复服务
GPU失败是因为驱动问题
解决驱动问题
1 | WHITE_WEBDEV_ENDPOINTS=https://alist.leioukupo.top/机械盘 |
1 | 机械盘/ |
1 | # 必须启用代理 |
Rock 5b卖掉后在咸鱼重新入手了一块3588,8+32的配置
需要debian系统
1 | curl -L https://mirrors.apqa.cn/proxmox/debian/pveport.gpg | sudo tee /usr/share/keyrings/pveport.gpg >/dev/null |
1 | echo "deb [deb=arm64 signed-by=/usr/share/keyrings/pveport.gpg] https://mirrors.apqa.cn/proxmox/debian/pve bookworm port" | sudo tee /etc/apt/sources.list.d/pveport.list |
1 | 127.0.0.1 localhost |
1 | sudo apt install ifupdown2 |
最后要记得重启,在访问ip+8006就可以访问pve管理界面了,密码和账号是root和对应的密码
使用非lxc容器方式
注意点
1 | apt download pve-edk2-firmware-aarch64=3.20220526-rockchip |
如果apt下载失败,复制pve-edk2到浏览器下载
虚拟机硬件里的显示需要选择ramfb方式
使用虚拟机安装
1 | qemu-img convert -f raw -O qcow2 istoreos-22.03.7-2024122712-h88k-squashfs-combined.img vm-101-disk-1.qcow2 |
打开刚才创建的虚拟机的硬件,会看到有个未使用的磁盘,双击打开,点确认即可
对应编辑一下引导顺序。
启动后,是uefi shell,没有进入istore界面,需要带efi的istore固件
1.先上传lxc模板,再执行下面的命令
1 | pct create 101 \ |
1 | 101是id号 |
2.修改lxc容器配置文件
1 | nano /etc/pve/lxc/101.conf |
1 | arch: arm64 |
3.在pve的web页面找到这个lxc容器,选项—》功能 —-》勾选嵌套
4.启动
1 | pct start 101 |
4.1修改/etc/config/firewall,后面新增
1 | lxc-attach 101 |
1 | config rule |
4.2.重启防火墙
1 | /etc/init.d/firewall restart |
1 | ifconfig |
根据ifconfig显示的ip访问就可以进入后台
1 | signals: |
使用signals声明,返回值是void
1 | emit sig_add(socre++); |
Qt的子线程无法直接修改ui,需要发送信号到ui线程进行修改
1 | qRegisterMetaType<Score>("Score"); |
Qt槽函数的参数需要和信号的参数保持一致, 可以比信号的参数少, 但是不能顺序不同, 也不能比信号的参数多
使用泛型解决信号重载问题
1 | connect(ui->comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), |
- 信号是由对象在某个特定事件发生时发出的消息。信号本身并不执行任何操作,它仅仅是表示某种状态的变化或事件的发生。例如,当一个按钮被点击时,它会发出一个
clicked()
信号- 槽是一个函数,可以接收并处理信号。当一个信号被发出时,与该信号连接的槽函数就会被调用。槽函数可以是任何成员函数、全局函数或lambda表达式
stm32f1没有内部温度传感器
1.开启对应时钟和ADC1时钟,设置PA1为模拟输入
1 | // 开启时钟 |
2.复位ADC1,同时设置ADC1参数
1 | ADC_DeInit(ADC1); |
3.使能ADC
1 | ADC_Cmd(ADC1,ENABLE); |
4.配置规则通道参数
1 | ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_7Cycles5); // 通道的转换顺序 如果设置Rank为1 |
5.开启软件转换
1 | ADC_SoftwareStartConvCmd(ADC1,ENABLE); // 软件触发转换 |
6.等待转换完成,读取ADC值
1 | ADC_GetConversionValue(ADC1); |
1 | RCC_APB1PeriphClockCmd() |
1 | PWR_BackupAccessCmd() |
1 | RCC_RTCCLKConfig() |
1 | RTC_Init () |
1 | RTC_SetTime () |
1 | RTC_SetDate() |
1 | RTC_AlarmCmd(RTC_Alarm_A,DISABLE) |
1 | RTC_SetAlarm() |
1 | RTC_AlarmCmd(RTC_Alarm_A,EABLE) |
1 | RTC_ITConfig() |
1 | RTC_Alarm_IRQHandler() |
1 | RTC_WakeUpCmd(DISABLE) |
1 | RTC_WakeUpClockConfig() |
1 | RTC_SetWakeUpCounter() |
1 | RTC_WakeUpCmd( ENABLE); |
1 | RTC_ITConfig() |
1 | RTC_WKUP_IRQHandler(); |
1 | //8个函数函数 |
1 | u8 usmart_get_parmpos(u8 num); // 得到某个参数在参数列里面的起始位置 |
pcnt & 0x7f 应该表示第几个参数
strtemp每次循环指向一个字符
首先判断接收到的字符串前五个字符是不是void, 设置rval, 是不是需要返回值
注意! 接收完前五个字符, 记得加’\0’ 字符串结束标记, 否则usmart_strcmp无法比较
下一个while判断当前字符是不是’*’或者’(‘ , 判断逻辑是, 没有碰到空格或者 * 就继续循环, 同时res也就是offset加1
根据offset直接跳到函数名开始的地方
继续判断, 逻辑是 fover表示碰到的括号, 左括号加一, 右括号减一, 如果fover是0说明没有接收完, 因为至少有一个左括号或有右括号
判断是不是’,’ 是,temp加一(temp表示参数个数)
1 | // 从str中得到函数名 |
比较两个字符串是不是一样, 和strcmp类似
1 | u8 usmart_strcmp(u8 *str1, u8 *str2) |
1 | // 获取下一个字符(当中间有很多空格的时候,此函数直接忽略空格,找到空格之后的第一个字符) |
初始化定时器, 使用的是定时器4, 主频也就是sysclk是72mhz, sysclk100-1是分频系数—> 72000000/(72 * 100-1 +1 )=10000hz, 所以一个定时器周期是1/10000==0.0001s==0.1ms, 定时器0.1ms1000====100ms中断一次
1 Timer4_Init(1000, (u32)sysclk * 100 - 1);
usmart_cmd_rec函数逻辑
入口参数是从串口接收到的函数名字, 字符串指针
首先通过usmart_get_fname得到函数名字和参数个数
然后从0到usmart_dev.fnum(结构体里函数数量值)开始循环, strcmp逐个比较接收的函数名字和本地存储的函数名字
情况1. 如果找到一样的,判断收到的函数参数是不是和存储的函数参数个数相等
情况1.1 收到的小于存储的就返回错误USMART_PARMERR, 记下函数id, 跳出循环
情况1.2 收到的大于存储的, xxxxxxxxxxx
情况1.3 收到的等于存储的, 用usmart_get_fparam获得函数参数个数并赋值给usmart_dev.pnum
情况3. 如果i循环到等于usmart_dev.fnum, 也就是全部找完了, 没有发现符合的函数名字,也返回一个错误USMART_NOFUNCFIND
都判断完,找到了且参数个数也一样就返回USMART_OK
1 | //入口参数是字符串指针 |
能够与同步或异步存储器和16位PC存储器卡连接,STM32的FSMC接口支持包括
SRAM
、NANDFLASH
、NORFLASH
和PSRAM
等存储器,支持8/16/32/位数据宽度。
fsmc驱动LCD的原理——->nor存储控制器把TFTLCD当成一个SRAM来用,有两个地址的SRAM
!注意:
当Bank1接的是16位宽度存储器的时候:HADDR[25:1]->FSMC_A[24:0];
当Bank1接的是8位宽度存储器的时候:HADDR[25:0]->FSMC_A[25:0];
不论外部接8位/16位宽设备,FSMC_A[0]永远接在外部设备地址A[0]。
STM32F4仅写时序DATAST需要+1
SRAM模式A
1 | //LCD地址结构体 |
1 | LCD_BASE,根据外部电路的连接来确定,如Bank1.sector4就是从地址0X6C000000开始,而0X000007FE,则是A10的偏移量 |