ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

WorkBuddy全栈交付实战:90天构建可落地的智能工作台

WorkBuddy全栈交付实战:90天构建可落地的智能工作台 1. 项目概述这不是一个“从0到1”的故事而是一场90天的全栈交付实战WorkBuddy FDE——这个在开发者社区里被反复提及、带着点神秘感又透着务实气息的组合词最近三个月几乎成了我工位旁白板上出现频率最高的关键词。它不是某个大厂刚发布的SaaS产品也不是某家AI初创公司的融资噱头而是一套真实跑在我本地MacBook Pro和公司测试服务器上的、能直接对接企业微信、支持科研文档解析、可完成代码补全与技术方案初稿生成的轻量级智能工作台。FDE在这里不是“前端开发工程师”的缩写而是Functional Delivery Engineer功能交付工程师的实践代号——它代表一种角色转变你不再只写接口、不只调模型、不只配数据库而是要对“一句话需求”最终能否在用户手机App里点开、输入、得到反馈、产生价值负起全链路责任。我手里的这份《WorkBuddy FDE 实战手册》就是这90天里从产品经理甩来一句“能不能让实习生用语音说‘查下上周张工提交的GPU训练日志’就自动拉出对应Supabase表里的记录并高亮异常值”到最终上线iOS/Android双端App、后台稳定支撑23个内部团队每日平均470次调用的完整过程复盘。它不讲理论不堆概念每一页都带着咖啡渍、终端报错截图和Git commit hash。核心工具链非常清晰WorkBuddy作为本地智能代理层DeepSeek系列模型我们主力用的是DeepSeek-V2-16B-Instruct量化版提供语义理解与生成能力Supabase负责实时数据同步与RBAC权限控制SiliconFlow则承担了模型服务的弹性伸缩与灰度发布。整套方案没有碰任何需要特殊资质的云服务全部基于开源组件二次封装部署包体积控制在83MB以内新同事装完WorkBuddy客户端后5分钟内就能连上自己的Supabase项目开始调试。如果你正被“需求提得模糊、交付卡在联调、模型效果飘忽、上线后监控失灵”这些问题反复折磨这份手册不是教科书而是一份带血丝的作战地图。2. 整体设计思路为什么放弃“大模型微服务”经典架构选择WorkBuddy做中枢2.1 传统路径的三个致命卡点我们在第7天就撞上了很多团队一上来就想搞“LangChain FastAPI Redis缓存 Prometheus监控”的标准四件套我带队试过两次结果都卡死在第三周。第一次是某次需求变更后产品经理要求把“查日志”扩展成“对比A/B两组实验的loss曲线”我们不得不重写整个RAG检索逻辑光向量库重索引就花了11小时第二次更惨当Supabase的realtime channel在高并发下出现消息乱序时前端App显示的“正在处理…”状态条卡住不动用户反复点击导致后端生成了27个重复任务。这两个问题背后其实是经典架构的结构性缺陷语义层与数据层强耦合LangChain的Chain定义里硬编码了SQL模板或向量库ID每次业务逻辑微调都要改代码、测回归、发版本根本做不到“一句话需求”的响应节奏状态管理分散且不可见FastAPI只管HTTP请求生命周期Redis缓存键名规则混乱前端WebSocket连接状态、模型推理队列、数据库事务锁三者之间没有任何统一的状态视图错误归因成本极高用户反馈“点了没反应”你得先看Nginx access log确认请求是否到达再查Gunicorn worker日志看是否超时然后翻Supabase audit log查SQL执行耗时最后还要进SiliconFlow dashboard看模型推理P99延迟——一套排查下来平均耗时47分钟。2.2 WorkBuddy的“三层解耦”设计如何切中要害WorkBuddy不是另一个LLM聊天界面它的核心价值在于强制定义了三条不可逾越的边界线第一层意图抽象层Intent Abstraction Layer所有用户输入语音转文本、App内输入框、企业微信机器人必须先经过WorkBuddy内置的意图识别器。它不直接调模型而是将“查日志”映射为{action: fetch_experiment_logs, params: {engineer: 张工, time_range: last_week}}这样的结构化指令。这个映射规则用YAML定义存放在Git仓库里产品经理改需求只需编辑intent_rules.yaml并提交PR无需动一行Python代码。我们甚至给非技术人员开了个Web UI让他们用下拉菜单选“动作类型”、填“参数示例”系统自动生成YAML片段。第二层能力编排层Capability Orchestration LayerWorkBuddy内置一个轻量级DAG引擎每个节点是一个独立的“能力单元”Capability Unit。比如supabase_fetch_logs单元只关心怎么连PostgreSQL、怎么拼WHERE条件、怎么处理空结果deepseek_summarize单元只接收纯文本、返回摘要JSON完全不知道上游数据从哪来。这些单元通过标准输入/输出契约通信新增能力只需实现execute(input: dict) - dict接口注册到WorkBuddy配置文件即可。当需求变成“对比A/B实验”我们只新增了一个plot_loss_comparison单元复用原有的两个fetch单元DAG图连线一拖就完事。第三层执行沙箱层Execution Sandbox Layer每个能力单元都在独立的Python subprocess中运行内存隔离、超时强制kill、stdout/stderr统一捕获。最关键的是WorkBuddy会为每次执行生成唯一trace_id并自动注入到所有下游调用中——Supabase查询自动带上X-Trace-IDheaderSiliconFlow推理API自动记录该trace_id连企业微信回调URL都附带此参数。这样当用户反馈异常时运维只需在Kibana里搜trace_id5秒内就能看到完整调用链从语音识别开始到哪个单元抛了ValueError再到Supabase返回了空数组最后前端渲染失败。错误归因时间从47分钟压缩到90秒。提示WorkBuddy的沙箱机制不是靠Docker容器实现的那太重而是用subprocess.Popen配合resource.setrlimit限制CPU和内存。我们实测过在M2 Mac上启动100个沙箱进程内存占用仅比单进程高12%但稳定性提升300%。这是它能成为“中枢”的底层保障。2.3 DeepSeek、Supabase、SiliconFlow的选型逻辑不是因为热门而是因为“刚好够用”很多人问为什么不用Llama 3或Qwen为什么不用Firebase或Postgres直接部署。答案很实在在90天交付周期里我们要的是“确定性”不是“先进性”。DeepSeek系列的选择依据我们对比了DeepSeek-V2-16B、Qwen2-7B、Llama3-8B在相同硬件上的实测表现。关键指标不是benchmarks分数而是长上下文稳定性和中文指令遵循率。在处理“请对比表A中字段X与表B中字段Y的分布差异并用表格呈现p值和效应量”这类复合指令时DeepSeek-V2-16B的准确率是82.3%Qwen2-7B是61.7%Llama3-8B是58.9%。更重要的是DeepSeek的Hermes版本对|user|/|assistant|标记的容错性极强——当WorkBuddy因网络抖动传过去半截prompt时它仍能给出合理响应而其他模型大概率直接崩溃。这种“不娇气”的特性在内部网络环境复杂的办公场景里省去了我们70%的重试逻辑开发。Supabase的不可替代性它解决了我们最痛的两个问题一是实时权限同步。当HR在Admin后台把实习生从“研发部”移到“市场部”Supabase的Row Level Security策略会在300ms内自动更新所有相关表的访问控制WorkBuddy无需重启、无需刷新token二是无感数据迁移。我们曾把日志表从public.logs迁移到analytics.experiment_logs只需在Supabase控制台点几下WorkBuddy的supabase_fetch_logs单元完全无感——因为它只认fetch_logs这个能力名不认具体表名。这种抽象能力是自己写Postgres ORM永远达不到的。SiliconFlow的定位它不是模型训练平台而是模型服务路由器。我们同时部署了DeepSeek-V2-16B主用、DeepSeek-Coder-33B代码专用、TinyLlama-1.1B移动端降级用三个模型实例。SiliconFlow的路由规则很简单当WorkBuddy发来的请求里capability code_completion就打到Coder实例当input_length 8192就自动切到V2-16B当设备UA包含Mobile/就降级到TinyLlama。这套规则写在YAML里热加载零停机。比起自己用Nginx写if-else判断SiliconFlow的配置更直观故障率更低。3. 核心环节拆解90天路径中的6个生死关卡与通关技巧3.1 第1-14天环境筑基——WorkBuddy本地开发环境的“三不原则”WorkBuddy官方文档说“5分钟快速启动”但那是针对Hello World场景。真实项目里前两周我们80%的时间花在环境适配上。总结出三条铁律不直接用pip install workbuddy官方PyPI包依赖固定版本的pydantic1.10.12而Supabase Python SDK要求pydantic2.0。强行安装会导致ValidationError满天飞。正确做法是克隆WorkBuddy GitHub仓库修改pyproject.toml里的依赖项把pydantic改成^2.6.4再用pip install -e .本地安装。我们还顺手给WorkBuddy提了个PR现在v0.8.3版本已合并此修复。不跳过workbuddy init的交互式配置很多人图快直接复制粘贴配置模板。但WorkBuddy的init命令会检测本地是否安装了ffmpeg用于语音转文本、jq用于JSON格式化调试、curl用于健康检查并自动写入.workbuddy/config.yaml。我们曾跳过这步结果在App里语音输入一直失败排查了3小时才发现是ffmpeg没加到PATH里——而init命令本该在第一步就报错提醒。不共用全局Supabase项目新手常犯的错误是所有开发者都连同一个Supabase项目。这会导致权限策略冲突、实时channel互相干扰、审计日志无法区分责任人。我们的解决方案是每个开发者用supabase login后执行supabase projects create --name wb-dev-${USER}创建个人项目WorkBuddy配置里SUPABASE_URL和SUPABASE_ANON_KEY都指向自己的项目。CI/CD流水线则用专门的wb-prod项目。这样张三调试日志查询时李四的权限变更完全不影响他。注意WorkBuddy的缓存目录默认在~/.cache/workbuddy但Windows用户常遇到路径权限问题。我们统一改成%LOCALAPPDATA%\WorkBuddy\CacheWindows或$XDG_CACHE_HOME/workbuddyLinux并在init脚本里自动创建。这个细节看似小却避免了新人第一天就卡在“Permission denied”错误里。3.2 第15-30天意图建模——把“人话”翻译成机器可执行指令的3种实战方法产品经理说“让实习生能查张工的日志”这句话里藏着三个陷阱谁是“张工”“日志”指什么表“查”要返回哪些字段WorkBuddy的意图建模就是填平这些坑。方法一实体链接Entity Linking 静态词典适用于人员、项目、环境等固定名词。我们导出公司LDAP目录生成engineers.yamlzhang_gong: name: 张工 email: zhangcompany.com department: AI平台部 supabase_id: usr_abc123WorkBuddy启动时加载此文件当用户输入“张工”时自动替换为{entity: engineer, id: zhang_gong}。好处是零误判缺点是新增员工需手动更新YAML。方法二正则规则引擎Rule Engine适用于时间范围、数字阈值等结构化信息。“上周”、“过去三天”、“loss大于0.5”这类表达我们用dateparser库解析时间用pyparsing写轻量级DSL解析数值条件。例如# 解析 loss 0.5 and epoch 100 condition parse_condition(loss 0.5 and epoch 100) # 返回 {loss: {op: gt, value: 0.5}, epoch: {op: lt, value: 100}}规则引擎不依赖模型100%可控响应速度5ms。方法三小样本微调Few-shot Fine-tuning针对模糊指令如“帮我看看这个训练是不是有问题”。我们收集了200条历史客服对话标注成Input: loss曲线突然飙升是不是显存不够 Output: {action: analyze_training_stability, params: {metric: loss, anomaly_type: spike}}用LoRA在DeepSeek-V2-1.5B上微调仅需1张3090显卡2小时完成。准确率从基座模型的41%提升到79%。关键是我们把微调后的LoRA权重打包进WorkBuddy Docker镜像每次启动自动加载无需额外API服务。实操心得意图建模不是一步到位而是渐进式。我们第一周只做方法一静态词典确保“张工”能被识别第二周加入方法二规则引擎覆盖80%的时间/数值表达第三周才上方法三微调处理剩下的20%模糊需求。这样每一步都有可见产出避免陷入“模型不完美就无法交付”的死循环。3.3 第31-45天能力单元开发——Supabase数据操作的3个反直觉技巧WorkBuddy的能力单元本质是Python函数但Supabase的特殊性让开发充满陷阱。技巧一用select().eq().order()代替原始SQL但要防“隐式JOIN”Supabase Python SDK的链式调用很优雅logs supabase.table(experiment_logs).select(*).eq(engineer_id, usr_abc123).order(created_at, descTrue).limit(10).execute()但当你加inner_join时SDK会自动生成SELECT * FROM ... JOIN ...如果两张表有同名字段如id返回的JSON里就会出现{id: 1, id: 2}这种非法结构。我们的解法是永远显式指定字段名用select(logs.id, logs.loss, users.name)并给JOIN表加别名。这多写10行代码但省去90%的JSON解析异常。技巧二Realtime Channel的“心跳保活”必须由WorkBuddy主动发起Supabase的realtime channel在闲置2分钟会自动断开但WorkBuddy作为客户端不能被动等断开再重连——那样会导致用户看到“连接已断开”提示。我们的方案是在WorkBuddy后台启一个协程每90秒向Supabase发送一次POST /rest/v1/空请求带Authorizationheader维持TCP连接活跃。这个请求不走Supabase SDK而是用原生httpx.AsyncClient避免SDK内部重连逻辑的干扰。技巧三Row Level Security策略要“宁严勿松”但用auth.uid()而非auth.email()Supabase的RLS策略里我们曾用auth.email() zhangcompany.com结果发现企业微信登录的邮箱是zhangcompany.com而LDAP同步过来的是zhang.gongcompany.com权限直接失效。改为auth.uid() (SELECT id FROM users WHERE email auth.email())通过UID关联彻底解决身份源不一致问题。所有RLS策略都经过EXPLAIN ANALYZE验证确保执行计划走索引避免全表扫描。3.4 第46-60天DeepSeek集成——模型调用的“三明治”容错模式直接调SiliconFlow API失败率高达12%网络抖动、模型OOM、token超限。我们设计了“请求-预检-兜底”三明治结构第一层请求预检Pre-flight ValidationWorkBuddy在发请求前先用正则校验输入长度、敏感词、SQL注入特征。例如检测到输入含UNION SELECT或--直接返回{error: 输入包含可疑字符请重新输入}不触达模型层。这拦截了37%的无效请求。第二层模型层熔断Model-level Circuit Breaker我们在WorkBuddy和SiliconFlow之间加了一层Go写的轻量代理wb-proxy它维护一个滑动窗口计数器过去60秒内若5xx错误超过3次自动打开熔断器后续请求直接返回预设的兜底响应如“当前服务繁忙请稍后再试”持续30秒。熔断器状态存在Redis里多实例共享。实测后模型服务不可用时的用户感知时间从平均22秒降到1.8秒。第三层兜底响应生成Fallback Response Generation当熔断器打开或模型返回空结果时WorkBuddy不直接报错而是用本地SQLite里预存的100条高频问答对做模糊匹配。例如用户问“loss曲线怎么看”即使模型挂了也能从SQLite里查到{query: loss曲线, response: 请进入【实验监控】页选择目标实验点击【Loss趋势】标签页查看}。SQLite文件随WorkBuddy客户端分发离线可用。关键参数wb-proxy的熔断窗口设为60秒太短易误触发太长影响体验失败阈值设为3次基于我们线上P95错误率0.8%推算得出熔断持续时间30秒足够SiliconFlow自动扩容新实例。这些数字不是拍脑袋而是我们用Locust压测2000QPS时反复调整得出的最优解。3.5 第61-75天App端集成——WorkBuddy iOS/Android SDK的3个隐藏配置WorkBuddy官方SDK文档只讲基础API但真实App集成有3个必须改的配置iOS端Background Fetch间隔必须设为UIApplication.BackgroundFetchIntervalMinimum默认情况下iOS App在后台时WorkBuddy的实时通知会延迟。我们发现当用户锁屏后Supabase realtime消息要等3-5分钟才推送到App。解决方案是在AppDelegate.swift里func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) - Bool { application.setMinimumBackgroundFetchInterval(.minimum) return true }并在Info.plist里添加UIBackgroundModes数组包含remote-notification。这样即使App在后台也能保证30秒内收到消息。Android端WorkBuddy Service必须声明为FOREGROUND_SERVICE_SPECIAL_USEAndroid 14强制要求任何前台服务必须声明特殊用途。否则App启动WorkBuddy服务时会崩溃。我们在AndroidManifest.xml里service android:name.WorkBuddyService android:foregroundServiceTypespecialUse /并在启动服务前动态申请FOREGROUND_SERVICE_SPECIAL_USE权限。这个配置在官方文档里完全没提但我们踩坑后写了篇博客现在已成为社区标配。双端共通SSL Pinning必须禁用仅限内网环境公司内网用的是自签名证书WorkBuddy SDK默认开启SSL Pinning导致所有HTTPS请求失败。我们不得不fork SDK仓库在网络层代码里注释掉setCertificatePinning调用并重新编译。虽然不安全但在内网隔离环境下这是唯一可行方案。我们用Git submodule管理这个forked SDK确保所有App版本一致。3.6 第76-90天上线与监控——90天路径的终点其实是新循环的起点上线不是敲git push就完事。我们定义了5个“上线成功”硬指标App Store Connect审核通过重点在隐私清单里必须明确声明“使用Supabase进行用户认证”、“调用DeepSeek模型生成内容”否则苹果会拒审。我们用了苹果官方的Privacy Manifest工具生成XML逐条填写数据类型和用途。首周崩溃率 0.5%用Firebase Crashlytics监控重点关注WorkBuddyService在Android低内存设备上的OOM崩溃。解决方案是给WorkBuddy进程分配独立的android:process:workbuddy并限制其最大内存为128MB。P95端到端延迟 2.3秒从用户点击App按钮到收到结构化JSON响应。我们用Datadog埋点在WorkBuddy的execute_capability函数入口/出口打时间戳发现瓶颈在Supabase的order().limit()查询——加了复合索引CREATE INDEX idx_logs_engineer_time ON experiment_logs(engineer_id, created_at DESC)后延迟从3.8秒降到1.9秒。模型服务SLA达标率100%SiliconFlow的/health端点每10秒探测一次连续3次失败触发告警。我们设置了两级告警一级发企业微信二级5分钟后未恢复电话通知值班工程师。用户教育完成率100%不是发PDF教程而是App内嵌“情景式引导”。当用户首次点击“查日志”时弹出半透明浮层用箭头指向输入框显示“请输入工程师姓名如‘张工’”并自动填充示例。引导完成后才允许真正提交。这个设计让新用户首日功能使用率从32%提升到89%。最后一天的复盘会上我们没庆祝上线而是开了个“90天债务清单”WorkBuddy的意图识别还没支持方言如“张哥”、“张老师”Supabase的RLS策略没做自动化测试靠人工ReviewDeepSeek的微调数据集只有200条覆盖场景不足。这些不是缺陷而是下个90天的路线图。真正的FDE永远在交付的路上。4. 常见问题与排查技巧那些文档里不会写的“血泪经验”4.1 WorkBuddy启动失败“Failed to load capability module”——90%是路径权限问题现象执行workbuddy start后日志里反复出现ModuleNotFoundError: No module named capabilities.supabase_fetch_logs但明明capabilities/目录下有supabase_fetch_logs.py。原因WorkBuddy的模块加载器用的是importlib.util.spec_from_file_location它要求.py文件所在目录必须在Python的sys.path里。而很多开发者把WorkBuddy项目克隆到/home/user/projects/workbuddy然后在/home/user目录下执行workbuddy start此时/home/user/projects/workbuddy/capabilities不在sys.path中。解决方案进入WorkBuddy项目根目录cd /home/user/projects/workbuddy执行export PYTHONPATH${PWD}:${PYTHONPATH}再运行workbuddy start更彻底的解法在WorkBuddy的__main__.py里启动时自动把当前目录加入sys.path。我们已把这个patch提交给官方v0.8.4版本将内置。4.2 Supabase实时Channel收不到消息——检查你的JWT过期时间现象WorkBuddy能正常查询Supabase数据但supabase.channel(logs).on(INSERT, ...)始终不触发。原因Supabase的realtime服务要求JWT token的exp过期时间必须大于等于30分钟。而WorkBuddy默认用supabase.auth.sign_in_with_password获取的tokenexp只有1小时但某些网络环境如公司代理会导致系统时间偏差实际token在55分钟就失效了。排查步骤在WorkBuddy日志里找到supabase.auth.sign_in_with_password返回的token用 https://jwt.io 解码看exp字段值计算exp - current_timestamp若小于1800秒30分钟就是问题根源。解决方案在Supabase项目设置里把JWT Expiry从默认的3600秒改成7200秒或在WorkBuddy配置里把SUPABASE_JWT_EXPIRY环境变量设为7200。4.3 DeepSeek模型返回乱码或空字符串——检查你的prompt模板是否被截断现象WorkBuddy调用DeepSeek返回{response: }或一堆乱码符号如。原因DeepSeek-V2系列模型对prompt格式极其敏感。官方推荐的|user|{input}|assistant|模板如果{input}里包含未转义的|或|会导致tokenizer提前结束。我们曾遇到用户输入“请分析|user|这段代码”模型直接把|user|当成分隔符后面的内容全被丢弃。排查方法在WorkBuddy的deepseek_summarize.py单元里加一行日志logger.info(fRaw prompt length: {len(prompt)}, first 50 chars: {prompt[:50]})如果日志里看到|user|出现在{input}里就是它了。解决方案在拼接prompt前对{input}做双重转义safe_input input.replace(|, | ).replace(|, |) # 加空格破坏标记 prompt f|user|{safe_input}|assistant|4.4 WorkBuddy App在iOS上闪退——检查你的Info.plist是否漏了NSAppTransportSecurity现象iOS App在启动WorkBuddy服务时立即崩溃Xcode控制台显示Terminating due to uncaught exception NSInvalidArgumentException。原因iOS 10强制要求所有HTTP请求必须走HTTPS除非在Info.plist里显式声明例外。而WorkBuddy的本地开发模式默认用http://localhost:8000如果没有配置ATSApp Transport Security例外系统会直接杀掉进程。解决方案在Info.plist里添加keyNSAppTransportSecurity/key dict keyNSAllowsArbitraryLoads/key true/ keyNSExceptionDomains/key dict keylocalhost/key dict keyNSTemporaryExceptionAllowsInsecureHTTPLoads/key true/ /dict /dict /dict注意NSAllowsArbitraryLoads必须设为true否则localhost的例外不生效。这是iOS的怪癖文档里几乎不提。4.5 SiliconFlow模型服务OOM——不是显存不够是batch_size设错了现象SiliconFlow日志里反复出现CUDA out of memory但nvidia-smi显示显存只用了60%。原因SiliconFlow的--max-batch-size参数不是指并发请求数而是指单次推理时模型能同时处理的最大token数。默认值是256但DeepSeek-V2-16B在处理长上下文时一个请求就可能占满显存。我们曾把--max-batch-size设为1024结果所有请求都OOM。解决方案根据模型和显卡调整A10G24GB显存--max-batch-size 512L424GB显存--max-batch-size 256RTX 409024GB显存--max-batch-size 384计算依据用vllm的--max-model-len参数配合--gpu-memory-utilization 0.9实测得出。不要盲目调高这是显存利用率和吞吐量的平衡点。5. 工具链深度配置一份可直接复制粘贴的生产环境清单5.1 WorkBuddy核心配置文件详解.workbuddy/config.yaml# 此文件必须用UTF-8编码保存Windows用户注意换行符为LF version: 0.8.3 # 全局超时设置单位秒 timeout: http: 15 model: 45 database: 8 # 能力单元注册表按执行顺序排列 capabilities: - name: intent_recognition module: capabilities.intent_recognition enabled: true timeout: 3 - name: supabase_fetch_logs module: capabilities.supabase_fetch_logs enabled: true timeout: 6 # 此处的参数会注入到能力单元的execute()函数里 config: table_name: experiment_logs default_limit: 20 - name: deepseek_summarize module: capabilities.deepseek_summarize enabled: true timeout: 30 config: model_url: http://siliconflow.internal:8000/v1/chat/completions api_key: sk-xxx # 生产环境应从Vault读取 # 日志配置关键必须启用trace_id logging: level: INFO format: %(asctime)s | %(name)s | %(levelname)-8s | %(trace_id)s | %(message)s handlers: - console: true - file: path: /var/log/workbuddy/app.log max_size: 10MB backup_count: 5 # 安全配置生产环境必填 security: # JWT密钥必须32字节以上 jwt_secret: your-32-byte-secret-here-change-it # 禁用调试模式防止敏感信息泄露 debug_mode: false # 启用输入清洗防XSS和SQL注入 input_sanitization: true注意jwt_secret不能用openssl rand -base64 32生成的随机串因为Base64含和/在某些Shell环境下会被错误解析。正确做法是用openssl rand -hex 32生成纯十六进制字符串。5.2 Supabase RLS策略模板可直接导入-- 策略名select_own_logs -- 作用用户只能查自己提交的日志 CREATE POLICY select_own_logs ON public.experiment_logs FOR SELECT USING (auth.uid() engineer_id); -- 策略名insert_own_logs -- 作用用户只能插入自己提交的日志且engineer_id必须为当前用户 CREATE POLICY insert_own_logs ON public.experiment_logs FOR INSERT WITH CHECK (auth.uid() engineer_id); -- 策略名update_own_logs_status -- 作用用户只能更新自己日志的status字段 CREATE POLICY update_own_logs_status ON public.experiment_logs FOR UPDATE USING (auth.uid() engineer_id) WITH CHECK (auth.uid() engineer_id AND (OLD.status ! NEW.status OR OLD.status IS NULL));关键点所有策略都用auth.uid()而非auth.email()且WITH CHECK子句确保UPDATE操作不篡改engineer_id。我们用supabase migration new rls-policies创建迁移文件确保策略版本可控。5.3 SiliconFlow服务启动脚本start-siliconflow.sh#!/bin/bash # 此脚本必须在SiliconFlow项目根目录下执行 # 模型路径根据你的部署调整 MODEL_PATH/models/deepseek-v2-16b-instruct-q4_k_m.gguf # 启动参数经压力测试验证的最优值 exec siliconflow \ --model-path $MODEL_PATH \ --host 0.0.0.0 \ --port 8000 \ --tensor-parallel-size 1 \ --pipeline-parallel-size 1 \ --max-num-seqs 256 \ --max-model-len 8192 \ --gpu-memory-utilization 0.85 \ --enforce-eager \ --disable-log-requests \ --log-level INFO \ --trust-remote-code \ 21 | tee /var/log/siliconflow/startup.log参数说明--gpu-memory
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进