在大陆地区使用GeminiPro搭建生成式聊天机器人

本文仅作技术方案记录 两周前偶然发现了一个基于GeminiPro接口的开源项目,可以一键搭建聊天机器人,于是准备尝试一下,并顺便找到一种可以直接通过国内网络访问的方式. 方案一:使用 Google Gemini API + Gemini Pro Chat + Vercel 部署聊天机器人 优点: 部署简单,易于使用。 Vercel 提供了开箱即用的解决方案,降低了开发难度。 缺点: 由于中国大陆的 GFW,无法通过在大陆直连的方式访问聊天机器人。 Vercel 的服务器位于海外,可能会导致访问速度较慢。 方案二:在访问域名前加上 Cloudflare 的 DNS 解析和 CDN 分发 优点: 绕过了 GFW,用户可以访问到部署在 Vercel 的页面。 Cloudflare 提供了全球化的 CDN 服务,可以提高访问速度。 缺点: 由于 Google 本身对于访问来源 IP 的限制,当用户访问 API 的时候,仍然会被 API 检测到来源 IP 是来自大陆,因此,这种方案虽然能让用户访问到部署在 Vercel 的页面,但是仍然无法使用 Gemini API。 方案三:将服务部署到个人美国 VPS 上面,再通过 VPS 上面现有的 Caddy 做了反向代理 优点: 隐藏了来源 IP,使 Gemini API 认为用户来自美国,因此实现了在中国大陆正常使用 Gemini API。 使用 Caddy 做反向代理,配置简单,易于使用。 缺点: ...

January 24, 2024 · 1 min · 141 words

ChatGPT初体验

在ChatGPT开放之初,注册了账号并体验了免费版的ChatGPT,总体感受还是比较震撼。给我留下最深印象的是它可以结合上下文和人类进行真正意义上的聊天。 最近开始尝试在Discord上玩各种基于ChatGPT的机器人,Midjourney Bot,ChatGPT Bot之类的。 今天在跟ChatGPT交互的时候发现model有一个选项是DAN,之前从未使用过,于是切换到DAN开始了体验。 以下是个人对ChatGPT默认model和DAN model的特点总结。 **AI(dan):**[GPT]: 始终保持客观,中立。 [DAN]: 根据问题的类型可能出现各种风格的回答,正如它的全称一样:“Do Anything Now”。 问题一 How to make a perfect Cappuccino? 相对中立,无立场的问题,DAN的回答保持了理性,客观。 ChatGPT的回答: To make a perfect cappuccino, you’ll need to start with a shot of espresso, steamed milk, and frothed milk. Begin by pulling a shot of espresso and then steaming the milk to a creamy consistency. Next, use the frother to create a thick layer of frothed milk, and then pour it on top of the steamed milk and espresso. The result should be a balanced and delicious cappuccino with a velvety texture and perfect foam. ...

February 20, 2023 · 3 min · 567 words

一些好的编程习惯

好习惯为何重要? 如果把编程比作一个游戏,一定是一个需要长期投入大量时间,精力的游戏。因为一个优秀的程序员不仅仅意味着掌握多项编程技术或技巧,更重要的是具备可以持续让自己的职业生涯受益的好习惯。 1. 身体的劳逸结合 身体是最重要的财产。保持良好的坐姿,半小时一次站立,走动或喝水。有条件的情况最好能每天进行有氧运动来保持良好的身体状态。 编程是一项脑力运动,但同样需要良好的身体作支撑。 2. 代码的简洁易读 不要过于追求代码设计模式的套用或是所谓的优雅,建议以结果为导向(result oriented)。不应该为了炫耀自己的代码多么优雅而写一些对于人类阅读不友好的骚操作。 代码的高可读性在CR,DEBUG和REFACTORING的时候非常重要。如果线上出现紧急故障,需要快速找出问题所在,可读性越高的代码将会在此过程中节省大量时间。 Keep it as simple, as consistent as possible! 3. 一段时间的持续专注 编程需要良好的专注力,每天可以尝试3-4小时的持续专注时间,在这段时间里不被周围环境打扰,工作可以变得非常高效。比如可以戴上降噪耳机或是告知周围的人让他们知道自己正进入一个专注的工作时间。 4. 跳出当下的舒适圈 就像我在16年的时候,当时每天在小型外包公司做着大量重复的工作:微信公众号网页开发,TP框架,CMS模板,前端的Jquery,数据库的CRUD,开发,生产环境的部署(当时也不知容器化为何物😓)。但那个状态对于当时的我来说也足够很轻松地应对每一天的工作,也大可不必学习新的技术(docker, cd/ci, 前端的spa相关)。但如果持续下去,我可能会丧失对新技术的兴趣,并且在未来1-2年内被完全淘汰(可能连小型外包公司都会嫌弃)。后来我主动跳出舒适圈,在持续的自学提升下找到了更好的工作机会。 5. 团队协作 开发是一个团队协作的过程,一个人独立完成所有工作并不是最高效的方式。在合适的时候与团队成员沟通或向他们请教可以很大程度提高效率,但注意:是在合适的时候。比如我遇到了一个问题,我通常应该在尝试过几种解决方式之后在去向同事请教,而不是直接把问题丢给同事。但也不能在遇到一个严重阻塞性问题的时候一直拖到任务将被delay的时候再提出来,应该把握好提出问题的时机。 6. 编程是"孤独"的 “孤独"是相对于其他职业而言的,因为每天需要对着电脑屏幕坐很长时间。作为程序员,我们应该适应这样的生活方式。 7. 具备快速学习的能力 通常来讲,技术的更迭速度是远快于我们的学习速度的。对于我们而言,能够用于学习的时间其实很有限(我们需要完成工作任务,照顾家庭,抽时间休息等等)。因此很多时候的学习其实是被动的:当一个需求/项目即将到来的时候,可能需要根据这个需求/项目中包含的技术栈去学习相应的自己尚未掌握的技能。这就需要我们具备高效的学习能力,掌握这种学习能力比学习某种技术/语言/框架更重要。 8. 更多关注项目的价值 技术(语言/框架等等)只是为需求服务的工具,再好的工具也需要合理的应用才能实现其价值。 举个🌰:不论用多少时间来学习了PHP或是Golang,在简历上通常也只是一句掌握PHP或是Golang。假如此时正在参加一场面试,掌握某种技术可能对面试官来讲只是大多候选人都应该具备的一个能力,但这可能并不够出众。而如果可以告诉面试官自己曾经通过某种技术在项目上的应用解决了某个难题或创造了多少额外收入,那么这个经历一定会是简历中的亮点。 Above Are Inspired By 7 Habits of Highly Effective Programmers (ft. ex-Google TechLead) Things I wish I knew when I started Programming

July 18, 2021 · 1 min · 62 words

我的2019

工作经历 经历前公司的倒闭和入职现在的公司, 在新公司负责C端的API开发,熟悉了不同场景下基于RPC,MQ的异步模式 通过大半年的工作积累,自己的业务理解能力比以往有所提高 折腾树莓派 把吃灰一年的树莓派3B重新拿出来玩,尝试过ubuntu server 19(preinstall version),ubuntu mate等发行版,最终还是用回raspbian版本,硬件驱动方面最省心. 树莓派上装了proxy软件,dnsmasq,ipset等工具用于协助实现透明网关(绕开dns污染,配合GFWList实现动态的域名访问proxy,配合脚本实现指定时间段指定域名列表的限制访问等);N个定时任务和N个@reboot任务用于实现如开机后自动播报本地内网IP,定时播报空气质量/天气预报,定时给儿子讲故事等功能;安装retropie用于模拟nintendo,mame,psp等平台游戏 学英语 做开发的时间越久越会发现这个技能是必不可少的,暂不说移民或外企,即便是网上Google一下日常技术问题,也会发现很多答案都是英文的,再加之目前的人工智障自动翻译水平有限,因此开始从下半年每天坚持学习英语,买了一款叫开言英语的App年会员,目前为止感觉还是有所提升 写在最后 2020年将继续以技术积累为主,同时坚持英语的学习

January 18, 2020 · 1 min · 15 words

简单记录下最近半年的变化

入职目前的公司已有半年,逐渐适应了新的业务和协作开发模式 今年的主要收获在于相对复杂业务需求的代码实现,开发过程中比以往更多的并发场景的处理,比以往更合理的代码封装 前段时间因为个人状态不是很好,因此暂停了更新,现在多数事情基本已经理顺,恢复博客更新

November 7, 2019 · 1 min · 3 words

在合适的场景使用延时队列代替定时任务

需求场景 当前有这样一个模块,用户A(被服务者)发布一个服务到平台,服务包含服务内容以及服务的开始和结束时间,用户B(服务者)可以选择预约用户A发布的服务 服务在被预约后会生成一个订单,用户B需要在服务开始时间到达时开始对用户A提供服务,并上传服务过程(手机拍照) 用户B在服务时间结束前完成全部服务过程的上传,用户A,用户B进行订单互评 流程结束 其中有4个时间节点需要系统自动处理: 距离服务开始前x(系统配置)分钟时,系统需要主动向用户B推送服务即将开始的通知 服务开始时间到达时,系统需要自动开始服务(更新订单状态为:服务中) 服务结束时间到达时,系统需要根据当前服务流程上传情况自动更新当前服务订单状态为:已完成/超时取消 对于已完成未评价的服务订单,系统需要在到达x(系统配置)小时后自动评价订单 解决方案 系统定时任务 最初使用了laravel自带的Task Scheduling处理以上流程,但是问题也不少: 由于需要批量查询,批量更新,后期数据量到达一定量级的时候mysql性能必然会受到较大影响 项目中对列表数据,详情数据几乎都使用了缓存,而缓存更新机制也是写在了laravel框架model层的events事件中,但是模型事件无法通过批量操作时触发(官网文档), 因此只能手动更新缓存 When issuing a mass update via Eloquent, the saved and updated model events will not be fired for the updated models. This is because the models are never actually retrieved when issuing a mass update. 时间粒度只能精确到分钟 延时队列 针对上述问题,我决定把这几个系统自动执行流程通过基于queues#delayed-dispatching重写(底层通过zset实现) 基本流程: 用户预约服务时将服务订单分发到两个队列(延时时间根据订单开始时间距离当前时间的差值决定[单位:s]):服务即将开始的通知队列,服务自动开始队列 服务开始时将订单分发到超时自动结束队列(延时时间根据订单结束时间距离当前时间的差值决定[单位:s]) 服务完成时将订单分发到超时未评价自动评价队列(延时时间根据系统配置订单完成后允许最长等待评价时间决定[单位:s]) 至此,通过延时队列解决了定时任务带来的问题

April 10, 2019 · 1 min · 60 words

如何坚持写博客

看到不少人说写博客很难坚持下去,在这总结下本人坚持写博客的动力 工作记录 做技术很多时候需要记录下开发过程中一些比较有意义的经历,比如解决了一个棘手的BUG,完成了一个对自己当前水平很有挑战的功能等等 这些记录都可能在日后遇到类似问题的时候不再踩坑,也可能帮助到他人 写博客的过程本身也是对所记录内容的一次情景重现,需要严格检查所记录内容是否正确,以免误导,自己再一次加深了对所记录内容的印象 技术总结 同上一个原因类似,我通常会在完成对一个或多个技术点的学习之后记录下学习过程,包括学习的动机,技术的应用场景,实现的过程等 折腾博客系统 从基于ThinkPHP3.2自己写的动态博客到hexo再到现在的jekyll,换过两次博客系统,周期性的替换博客系统也是玩独立博客的乐趣之一 博客主题也是换过多次 生活记录 除了技术相关的内容,博客用来记录生活的点滴也是不错的 保持学习 只有坚持不断的学习,才会有更多写博客的欲望,才会有更多需要记录的东西,因此这点可以从根本上解决不能坚持写博客的问题~ 以上都是本人坚持写博客的动力

April 9, 2019 · 1 min · 15 words

redis在目前项目的部分应用场景

场景一:设备在线状态保持 需求 有若干台设备,设备具备定时向server发送heartbeat的功能,后台需要在设备列表实时监控设备的在线情况(允许有不大于5分钟的时间延迟) 实现 在openresty配置中加入用于处理心跳请求的location块,如下 location /device/heartbeat { default_type text/html; lua_need_request_body on; content_by_lua_file src/heartbeat_detector.lua; } lua脚本 -- 获取请求方式,只允许POST请求 local request_method = ngx.var.request_method -- ngx.log(ngx.ERR, "headers:"..ngx.var.http_user_agent) if request_method ~= "POST" then ngx.exit(ngx.HTTP_NOT_ALLOWED) end local function close_redis(red) if not red then return end --释放连接(连接池实现) local pool_max_idle_time = 10000 --毫秒 local pool_size = 100 --连接池大小 local ok, err = red:set_keepalive(pool_max_idle_time, pool_size) if not ok then ngx.log(ngx.ERR, "set redis keepalive error : ", err) end end -- 引入json处理库 local cjson = require "cjson" -- 临时文件读取函数 function getFile(file_name) local f = assert(io.open(file_name, 'r')) local string = f:read("*all") f:close() return string end -- 获取请求体 ngx.req.read_body() -- 获取请求body local data = ngx.req.get_body_data() -- 如果请求body为空,则从临时文件获取 if nil == data then local file_name = ngx.req.get_body_file() if file_name then data = getFile(file_name) end end -- 将data转换为object local obj = cjson.decode(data) -- 如果当前请求为心跳维持请求 if obj.Name == "KeepAlive" then --[[ 初始化redis ]] local redis = require "resty.redis" local red = redis:new() red:set_timeout(1000) local host = 'ip' local port = port local ok, err = red:connect(host,port) if not ok then return close_redis(red) end -- 请注意这里 auth 的调用过程 local count ount, err = red:get_reused_times() if 0 == count then ok, err = red:auth("password") if not ok then ngx.say("failed to auth: ", err) return end elseif err then ngx.say("failed to get reused times: ", err) return end -- redis前缀 local prefix = 'device_heartbeat:' -- 缓存心跳 res, err = red:set(prefix..obj.DeviceId, 1, 'EX', 300) end 需要保证在项目的已有路由中没有/device/heartbeat,此时/device/heartbeat的请求会交给lua脚本处理,相对于php性能消耗更少,php后台获取到数据后可直接在redis中查找该设备对应的心跳key是否存在来确认设备是否在线 ...

April 3, 2019 · 3 min · 613 words

开始在ubuntu下工作

由来 家里的PC机有几个月没用了,昨天刚开机,发现SSD识别不了,经过排查,确定是盘坏了,然后只能重装 之前用的win10做开发环境,但是觉得windows还是更适合作为游戏机存在,家里又有台MBP,因此考虑到没怎么用过linux桌面版的情况,决定感受下ubuntu 分区 PC配置是12GB内存,硬盘是1T+5T,1T的硬盘装数据装得差不多了,5T的还有4个T没分区,因此直接装在了5T这个盘上,200G挂载在/目录,100G挂载在/home目录,14G分到SWAP交换分区,500M分到EFI启动分区,BIOS中进行了UEFI启动配置 科学上网 linux下面的科学上网相比于windows,darwin,android,ios系统相对繁琐,首先安装好ss,开启ss后配置系统代理到ss中的本地端口 如果要实现浏览器根据GFWList规则上网,以chrome来说,需要下载一个插件:SwitchyOmega,并按照流程配置 如果要实现terminal科学上网,则需要安装proxychains sudo apt-get install proxychains 编辑配置文件 mkdir -p /home/lestat/.proxychains/ sudo vim ~/.proxychains/proxychains.conf 如下配置(协议,ip,端口根据实际情况配置) strict_chain proxy_dns remote_dns_subnet 224 tcp_read_time_out 15000 tcp_connect_time_out 8000 localnet 127.0.0.0/255.0.0.0 quiet_mode [ProxyList] socks5 127.0.0.1 1080 之后在需要ss的命令前加proxychains,如: sudo proxychains git clone https://github.com/lestat220255/docker-lnmp.git docker开发环境 在安装完docker和docker-compose之后,使用我之前写的脚本,快速搭建docker+nginx+php+mysql+redis的开发环境,同时支持各种服务的多版本并存,后期开发非常方便,摆脱了集成环境的同类服务只能运行一个版本的约束 sudo proxychains git clone https://github.com/lestat220255/docker-lnmp.git cd docker-lnmp && chmod u+x ./init.sh && ./init.sh 工具推荐 terminal扩展 proxychains git npm相关 docker相关 ntfs-3g(用于挂在windows ntfs分区的工具,如果电脑是双系统,强烈推荐) rdesktop(连接windows server) OhMyZsh tldr htop(top加强版) 社交 telegram(推荐安装一个chrome/firefox插件更方便使用) 网页版微信 科学上网 shadowsocks-qt5 proxychains(terminal) SwitchyOmega(用于浏览器上根据GFWList自动切换系统代理或是直连) 开发工具 vscode(简直不能更好用…) phpstorm(2018.1.6)更新的版本无法使用之前的激活服务器 pycharm(个人版,免费) postman 其他 搜狗拼音 坚果云 FileZilla Wps vps网速测试wget -qO- git.io/superbench.sh | bash frp(内网穿透,可以用于开发测试,接收支付回调) 关闭程序崩溃报告 查看当前有哪些程序的崩溃记录 ls /var/crash 直接删除它们,但后续如果有类似报告依然会提示 sudo rm /var/crash/* 修改配置为0即可禁用报告(彻底解决问题) vim /etc/default/apport Change the enabled=1 to enabled=0. Save and close the file. You won’t see any pop up for crash reports after doing this. Obvious to point out that if you want to enable the crash reports again, you just need to change the same file and put enabled as 1 again 参考原网址 安装主题管理 sudo apt-get install unity-tweak-tool sudo apt-get install notify-osd && sudo apt-get install overlay-scrollbar nohup unity-tweak-tool>/dev/null 2>&1 & 一站式搞定theme,icon,dock ...

September 24, 2018 · 2 min · 224 words

北海三日游

比较有特色的一座滨海城市,当地的人也很友好,少了一些浮躁 

August 15, 2018 · 1 min · 2 words