构建垂直市场代理
一个聊天代理,它在特定行业和都市区超越了通用模型,因为它携带了预计算的真实数据摘要,并能在对话过程中实时拉取记录。完成 = 在线运行于一个URL上,能够回答并引用基板中的具体数据,拒绝编造没有的数据,并通过真实的生产环境探测(而非本地测试)验证。
第0步:所有者回答的两个问题
- 哪个都市区,为什么选它? 选择你已经在此处进行过实地工作或拥有真实数据的地方。先挖掘一个都市区的数据,再在那里做广告。
- 会做广告吗,是否与位置关联? 四个工程决策与此相关(像素、缓存TTL、自定义URL、归因)。参见第7步。
第1步:在编写代码之前找到护城河
两种类型:你挖掘并拥有的语料库(例如数万条评论),或一个关联(实时在售房源与县土地、估值和税务记录的关联:两个免费且无人愿意合并的数据源)。付费批量枚举往往会失败(积分用完、缺乏所有者搜索支持)。
当批量枚举受限时,入口点是约束,而非数据本身。 一个能回答任意地址但不会列出所有地址的县级应用,只要你能在其他地方枚举出地址(第3步),就没有问题。
非公开州是一个机会:没有人拥有销售对比数据,包括竞争对手,因此该县自己的良好组织的计算就成为了最佳锚点。
第2步:构建基板
一个冻结的JSON摘要,通过服务端在每条消息中注入到系统提示中。
- 首先检查面板规模(针对评论语料库代理)。“你在同类场所中的排名”需要约50个以上各有50条以上评论的商家。低于此阈值,不要发布排名。
- 模型撰写的行业概况不是基板。 加载模型自己写的文字告诉模型它已经知道的东西,且不构成任何护城河。基板必须是可测量的。
- 缺失数据是待办事项,而非障碍:如果你拥有挖掘面板的方法,就去挖掘它。
- 挖掘前检查许可证。 某些来源的数据不可重新分发,这决定了挖掘到的面板是否永远无法作为下载提供。
- 每个数据块都带有
_interpretation:2-4句话,说明其含义及专业人士如何使用它。每字节价值最高;这是背诵和推理之间的区别。 - 字节稳定的输出:
sort_keys=True,全局排序时在唯一字段上打破平局,不包含时间戳(除了generated_on)。一个变化的字节会在每条消息上重新结算缓存的公共前缀。 - 分层,并让更好的层取代旧层;两个数据块对同一问题给出不同数字会使模型在回答中进行仲裁。当数据块混合时,在子键级别进行取代。
- 存档全量,发布紧凑(
.compact.json孪生文件),如果紧凑版本缺失则回退到存档。 - 从合并的研究中清除个人电子邮件:在广告规模下,模型可能将一个公务员的收件箱变成你的出站渠道。部门+电话号码已经足够。
第3步:枚举记录无法覆盖的内容
一个简单的列表信息源几乎看不到什么。在网格上的小圆内“搜索附近”的地点,然后将每个命中点关联到县记录(一次运行:307个综合体 -> 208个匹配的地块 -> 9,736个单位)。
- 小圆(在约3.9公里的网格上约3.5公里半径):API限制了每次调用的结果数量,因此一次全城范围的查询只会静默地返回最知名的地方。
- 让公共记录决定事物是什么,而不是你枚举的来源(一个目录中的“公寓”在县记录中可能是护理设施;一个被标记为多户住宅的二手车停车场)。
- 在一个几乎没有房源列表的市场中,值得交谈的人是那些不出售的人。
第4步:数据陷阱(读两遍)
这里的每一个Bug都产生了一个看似合理但错误的数字,从未触发错误。 预算的QA时间对照一个已知正确的基准。
- 在围绕某个来源描述进行规划之前,重新查询该来源。 文档中的图层名只是一个假设。在信任字段名之前,请阅读服务的元数据(对于ArcGIS
?f=json,editingInfo.dataLastEditDate)和实际的字段值。 - 与你已知的信息进行验证。 一栋已知有36个单元的建筑物被解析为10个:一个基准捕获了最严重的Bug。更好的是,将你的一部分输出以不同的坐标框架发送回发布者的自有API并比较。
- 注意倒置,而不仅仅是异常值:小地产每扇门估值高于大地产意味着解析器有误,而不是市场问题。
- 让数据自我检查。 在存在交叉检查(每单位平方英尺)的地方,计算歧义字段的两个读数,让合理的波段选择;如果两者都不合适,则标记并排除。
- 在聚合之前去重。 一个信息源将所有符合的资产类型下的同一物业都列出:623行实际上是206个物业。
- 缓存原始数据(RAW),绝不要缓存解析后的数据,否则解析器修复意味着必须重新爬取一个小县的服务器。
- 地址格式与记录索引不同。 缩写方向词并删除后缀;一个变体阶梯恢复了大约一半的遗漏匹配。
- 用小样本的n值进行标记;有时稀疏本身就是发现。
- 在评论语料库上,阅读匹配项(MATCHES),绝不要阅读比例。 将每个分类正则表达式应用于真实的1-3星文本并阅读匹配的结果。该行业常用的服务动词往往是一个伤害动词:
cut (me|my)上的“伤害”模式匹配了10.7%的沙龙投诉,其中大部分是“付了40美元剪自己的头发”。检查drill(牙科)、pull(拖车)、strip(清洗)、break(玻璃)、shave/clip(理发、美容)、stick(验血)。而且,一个没有人提出的主题会被忽略。 - 发布者的词汇不是买家的词汇。 一个县的“主干道”类别可能是高速公路网络,那里没有临街建筑,而经纪人所说的商业街道却是“集散道路”。在映射之前列出每个桶的内容,并根据其内容命名字段。
- 共享模式共享列名,而非约定。 跨县时,一个字段可能携带四套分类系统,
-9999vs0,或第三套房产税优惠价值。对每个县的每个字段进行普查;将来自某个县的零视为查询Bug,直到证明并非如此;优先使用派生测试(建筑价值=0且土地价值>0表示空地)。 - 一个名称对应多个事物(一条高速公路及其辅路共享一个名称)。返回替代项,让模型说明它使用了哪一个。
- 本应相交一次的事物多次相交(两条路在六个地方交叉)。计算平均点会落在空地上;聚类,保留每个位置,按明确规则选择。
- 派生总数会静默地丢弃你从未计算过的行。 在任何使用部分输入的总计旁边提供覆盖计数,并使其读作下限。
第5步:确定性数学放在工具中,绝不放在提示词里
DSCR、IRR、现金回报率、剂量、税费:一个工具,进行计算,返回其假设和警告。模型的算术是看似合理的错误(一个1.19的DSCR实际上是1.09,会被发送给贷方)。这强制了一个真实的代理循环(流式输出 -> 运行工具 -> 反馈 -> 流式输出),包括处理pause_turn和max_tokens。
第6步:测量提示成本
- 使用API计算Token。 密集JSON大约是2.4字节/Token,而非约4字节/Token。
- 在测试中强制设定字节/Token上限:发布存档而非紧凑孪生文件除了账单增加外没有任何症状。
- 缓存TTL根据流量调整。 稀疏、手工分享的流量:5分钟默认(1小时的写入是没人重用的附加费用)。持续的付费流量:1小时,因为访客共享公共前缀。
第7步:发布
- 从一个生成器派生页面;每次替换都断言其锚点存在,且守卫检查双向(被移除的内容确实消失并且功能幸存)。
- 如果它是广告目的地:自定义URL使用临时重定向(永久重定向会被广告平台缓存),验证查询字符串幸存;每个广告系列对应一个像素事件名称;缓存TTL为1小时;并且归因固定在
sessionStorage中,在到达页命中时设置,并在每次对话轮次中携带(不要用localStorage,否则下一周的自然访问会归功于今天的广告)。 - 验证部署状态,而非构建日志;一个无服务器函数上限或未跟踪文件可能在绿色日志背后失败。静态导入数据文件,以便打包程序包含它们。
提示词的硬性规则
- 绝不发明数字。 必须是基板、实际调用的工具调用或标记的估算值。
- 绝不以市场价值的形式呈现公共记录值。 说明你给出的是哪个。
- 在工具描述和提示词中都说明覆盖范围边界(哪些县)。只在其中一个地方写规则会被绕过。
- 一次只能查询一条公共记录,不能以列表形式查询。 查询所询问房产的所有者是可以的;批量名称和地址的名册可能违反州公共记录法关于商业使用的规定。
- 重新检查提示词认为是不可行的事情。 关于无法知道的事情的自信错误判断比数据空白更糟糕。
用于上下文层的研究代理
给并行研究代理一个Token预算(以及2.4字节/Token的比例),告诉它们保留数据而非注释,并期望它们纠正你之前的工作。
第8步:行业外用户的终结方案
一些访客不是它的目标用户(比如在餐厅代理中找到一家旧货店)。默认的“我没有这个信息”会让你失去你能得到的最佳信号:一个真正的企业主,可能告诉你下一个要构建的行业。
- 一个
flag_out_of_scope(sector)工具:客户端渲染三个可点击的选项;一个submit_feature_request工具记录点击。 - 所有内容都在第一次回复中:中位会话深度为一次轮。
- 不要罗列代理本身携带的内容(一次删减将回复从1,275个字符减少到124个字符)。
- 选项是客户端渲染的,绝不是散文中的编号列表(裸的“2”可能触发技能2)。
- 告诉模型选项在哪里渲染;模型无法看到客户端。
- 将选项映射到通用能力,以便提交的请求命名某个行业的一种能力。
第9步:空间图层(“这个旁边是什么”)
- 找到县的ArcGIS Online组织,而不是其被WAF阻止的GIS主机;托管服务通常支持匿名访问。以图层的本机空间参考请求几何。
- 当两个来源不同时,以第一个来源的坐标系请求第二个来源(
outSR),并在输出行之前断言范围重叠:坐标系不匹配会导致无相交,并报告“所有地块均无分区”。在DuckDB中,ST_Transform需要always_xy := true,否则会静默返回POINT(inf inf)。 - 按质心进行分区;分区边界地块需要一个份额阈值(>5%的地块面积),比较的是区域而非多边形。裸的相交调用导致37%的地块被标记为分裂;阈值则降至约4%。
- 一个城市的分区代码属于该城市。 相同的代码在隔壁可能意味着不同的区域;在每个代码旁附带城市名称和发布名称。
- 离线预计算,发布无几何的索引,不添加API路由:县GIS -> DuckDB空间镜像 -> 一个提交的JSON索引;运行时仅执行查找和Haversine计算。失败的空间依赖会退化为空邻居列表,这是一个自信的错误答案。在加载时验证索引并抛出异常。
- 空间连接中的任何不等式条件都会将空间谓词降级为后过滤器(
ON a.id < b.id AND ST_Intersects(...)测试了约29亿个配对)。让谓词独立存在,EXPLAIN执行计划显示SPATIAL_JOIN,发射键,然后去重:7分钟未完成变为19秒。 - 将发布的索引范围限定在买家交易区域加上直接邻居,并标记携带较少数据的“上下文”地块。