OpenClaw运维实战:HZERO Agent词典向量同步失败问题排查与修复

使用OpenClaw AI运维助手排查HZERO AIP Agent词典向量同步失败问题,从日志分析、根因定位到修复验证的完整过程。collection_name字段为空导致collectionName is blank异常,3分钟完成修复。

背景

在HZERO PaaS平台的AIP(AI Platform)模块中,Agent词典是AI智能体理解业务语义的关键组件。词典中的每个条目会被同步到向量数据库和ElasticSearch中,供Agent在对话时进行语义匹配。

某天在HZERO开发环境中,发现词典「对象使用方式」(编码:HMDE.BUSINESS_OBJECT.USE_TYPE)下的三个条目(CREATE、MODIFY、MATCHING)全部显示「(向量)同步失败」,而ES同步正常。向量同步时间停留在很久以前,ES同步时间则是刚刚更新的。

本文记录了使用OpenClaw(AI运维助手)从发现问题到定位根因、修复验证的完整过程。

问题现象

条目 向量状态 向量同步时间 ES同步时间
CREATE 🔴 同步失败 2025-06-03 08:00:00 2026-07-04 12:35:25
MODIFY 🔴 同步失败 2025-06-03 08:00:00 2026-07-04 12:35:25
MATCHING 🔴 同步失败 2025-06-03 08:00:00 2026-07-04 12:35:25

关键观察点:

  • 界面显示「向量库集合:haip_dictionary_value_0(已加载)」,看似配置正常
  • ES同步完全正常,只有向量同步失败
  • 三个条目同时失败,不是个别数据问题

排查过程

第一步:检查服务状态

首先确认AIP相关服务是否正常运行:

docker ps --filter name=hzero-aip --format "table {{.Names}}	{{.Status}}"

结果:hzero-aip-serverhzero-aip-app 均正常运行,排除服务宕机问题。

第二步:查看服务日志

检查AIP服务最近1小时的日志,过滤向量同步相关错误:

docker logs hzero-aip-server --since 1h 2>&1 | grep -iE "vector|向量|sync.*fail|embedding.*error" | tail -30

立刻发现大量重复错误:

ERROR - Unexpected exception occurred invoking async method: 
  DictionaryVectorRepositoryImpl.remove()

java.lang.IllegalArgumentException: collectionName is blank
    at CollectionRequest$Builder.build(CollectionRequest.java:87)
    at VectorDb.exists(VectorDb.java:125)
    at VectorDb.deleteByCondition(VectorDb.java:256)
    at DictionaryVectorRepositoryImpl.remove(DictionaryVectorRepositoryImpl.java:189)

核心错误:collectionName is blank — 向量集合名称为空。

第三步:检查数据库配置

错误明确指向集合名称为空,直接查数据库确认:

SELECT dictionary_id, dictionary_code, collection_name, sync_type 
FROM hzero_aip.haip_aigc_dictionary;

结果:

dictionary_id dictionary_code collection_name 状态
2 HMDE.BUSINESS_OBJECT.USE_TYPE (空) 🔴 问题所在
3 LOWCODE.DOMAIN (空) 🔴 同样有问题
7 HAIP.APPLICATION_LINK haip_dictionary_value_0 ✅ 正常

根因确认:词典ID 2和3的 collection_name 字段为空,而词典ID 7有值且正常。

第四步:分析为何界面显示正常但实际失败

这里有一个容易误导的点:界面上明明显示「向量库集合:haip_dictionary_value_0(已加载)」,为什么数据库里是空的?

通过进一步分析日志,发现同步流程分为两个阶段:

  1. remove阶段(清理旧向量):直接读取Dictionary实体的 collection_name 字段 → 为空 → 抛 collectionName is blank 异常 → 失败
  2. doSync阶段(写入新向量):通过其他途径(可能是全局配置或Redis缓存)获取到了集合名 haip_dictionary_value_0 → ES操作实际执行 → 成功

由于同步流程是「先remove → 后doSync」,remove阶段失败导致整个同步任务被标记为「失败」,尽管后续doSync的ES操作实际已执行。

界面显示的集合名来自运行时全局配置,而非该词典的 collection_name 字段,因此看起来「正常」。

根因总结

层面 说明
直接原因 haip_aigc_dictionary 表中部分词典的 collection_name 字段为空
触发条件 向量同步时 remove 阶段直接使用该字段,为空即抛 IllegalArgumentException
误导因素 界面通过全局配置显示集合名,掩盖了字段为空的事实
影响范围 dictionary_id=2(对象使用方式)和 dictionary_id=3(低代码领域)

修复方案与执行

修复SQL

UPDATE hzero_aip.haip_aigc_dictionary 
SET collection_name = 'haip_dictionary_value_0' 
WHERE dictionary_id IN (2, 3);

完整修复步骤

1. 执行SQL补全字段

docker exec mysql-hzero mysql -uhzero -phzero -e "
UPDATE hzero_aip.haip_aigc_dictionary 
SET collection_name = 'haip_dictionary_value_0' 
WHERE dictionary_id IN (2, 3);"

2. 清除Redis向量集合缓存

docker exec redis-hzero redis-cli -n 1 DEL   "haip:config:vector:collection:DEFAULT_ES"   "haip:config:vector:collection:DEFAULT"   "haip:config:vector:database"   "haip:config:vector:database:last-updated-time"

3. 重启AIP服务

docker restart hzero-aip-server

4. 界面重新触发向量同步

在HZERO AIP → Agent词典 → 对象使用方式 → 数据同步 → 向量同步

结果:三个条目全部显示「已同步」✅

OpenClaw运维价值体现

这个问题如果纯人工排查,典型流程是:看界面 → 查日志(在大量日志中找关键错误)→ 理解Java调用栈 → 关联数据库配置 → 发现字段为空 → 分析为何界面显示与实际不符。整个过程至少30-60分钟。

使用OpenClaw的排查过程:

步骤 操作 耗时
1. 服务状态检查 docker ps 确认服务运行 ~5秒
2. 日志错误提取 grep 过滤关键错误,定位异常堆栈 ~10秒
3. 数据库验证 SQL查询确认 collection_name 为空 ~5秒
4. 根因确认 分析调用链,解释界面与实际不一致的原因 ~10秒
5. 修复执行 SQL + Redis缓存清除 + 服务重启 ~30秒
6. 验证 用户界面触发同步,确认成功 ~1分钟

从问题报告到修复完成,全程约3分钟。OpenClaw的核心价值在于:

  • 快速定位:自动执行服务检查 → 日志分析 → 数据库验证的完整诊断链路
  • 准确分析:理解Java异常堆栈,关联数据库配置,解释表面现象与根因的差异
  • 安全修复:执行精确的SQL修复,清除相关缓存,重启服务,全流程闭环
  • 知识沉淀:问题分析过程自动记录到工作日志,便于后续回顾

经验总结

  1. 界面显示 ≠ 数据库实际值:HZERO很多界面字段来自运行时全局配置或缓存,不直接反映数据库字段值。排查问题时要以数据库为准。
  2. 同步流程是多阶段的:向量同步包含 remove → doSync 两个阶段,任一阶段失败都会标记整体失败。看日志要关注失败发生在哪个阶段。
  3. Redis缓存是常见陷阱:修改数据库后必须清除对应Redis缓存,否则服务可能仍读取旧值。这次修复也包含了缓存清除步骤。
  4. collection_name 是关键配置:HZERO AIP的向量同步依赖此字段,初始化环境时应确保所有词典都有正确的集合名。

环境信息

  • 平台:HZERO PaaS + AIP 1.6.1.ALPHA.6.13
  • 向量数据库:ElasticSearch(作为向量存储后端)
  • 缓存:Redis DB 1
  • 部署方式:Docker 容器化
  • 运维工具:OpenClaw AI运维助手

视频信息

 

视频演示

OpenClaw排查HZERO Agent词典向量同步问题全过程:

视频地址:https://www.bilibili.com/video/BV1uxMw6kEwG

AI Agent 问题排查实战:HZERO 低代码 AI 助手故障诊断与修复

一、背景

HZERO 低代码平台提供了「AI 助手」功能,用户通过上传界面截图或描述需求,AI 自动生成业务对象和页面。该功能由 AIP(AI 平台)的 Agent 编排实现,涉及 hzero-aip-apphzero-aip-serverhzero-modeler 等多个微服务协同。

测试过程中连续遇到两个错误,本文记录了作为 AI Agent 如何逐步分析、定位并解决问题的完整过程。

二、问题一:domainCode 缺失

2.1 现象

在 AIP 中台直接调用「AIGC 生成低代码业务对象和页面」Agent 编排,执行到「批量创建对象」节点时报错:

CommonException: 程序出现错误,请联系管理员

2.2 分析过程

第一步:看截图,定位错误节点

用户提供了错误截图,显示错误发生在流程的「批量创建对象」节点,异常类型为 CommonException,调用栈指向 AbstractInnerRequestNodeHandler.execute

判断方向:这是 Agent 流程中的内部接口调用节点,调用了低代码平台的后端接口,接口返回了错误。

第二步:查容器状态,确认服务存活

docker ps --format '{{.Names}}\t{{.Status}}' | grep -i aip

结果:hzero-aip-serverhzero-aip-app 都 Up 7 hours,排除服务宕机。

第三步:拉日志,精确定位错误

先看 hzero-aip-app(Agent 流程执行方)的日志,过滤错误关键词:

docker logs hzero-aip-app --since 30m 2>&1 | grep -i "error\|exception\|批量创建\|InnerRequest" | tail -50

找到关键错误:

ERROR --- Failed on node AIGC 生成低代码业务对象和页面/LOWCODE.BUSINESS_OBJECT_PAGE/INTERNAL_INTERFACE_...
io.choerodon.core.exception.CommonException: 程序出现错误,请联系管理员
  at ResponseUtils.getResponse(ResponseUtils.java:133)
  at AbstractInnerRequestNodeHandler.execute(AbstractInnerRequestNodeHandler.java:199)

这说明 aip-app 调用了某个内部接口,接口返回了非成功响应,ResponseUtils 解析后抛出通用异常。

第四步:查被调用方日志,找到真实错误

错误堆栈显示调用链终止在 aip-app,但真正的错误来自被调用的服务。查看 hzero-modeler 日志:

docker logs hzero-modeler --since 30m 2>&1 | grep -i "error\|exception\|simple-generator" | tail -30

找到根因:

MissingServletRequestParameterException: Required request parameter 'domainCode' for method parameter type String is not present
  Request: {URI=/v1/0/business-objects/domain/simple-generator}

第五步:回溯参数,确认 domainCode 为 null

回到 aip-app 日志,查看脚本节点的参数输出:

脚本节点参数:{businessObjectList=[...], domainCode=null, pageList=[...]}

确认domainCode 为 null,导致低代码平台接口报 400 错误。

2.3 根因

Agent 编排流程中,domainCode 需要从低代码平台的上下文中获取。用户直接在 AIP 中台调用 Agent 编排,没有进入低代码平台的领域上下文,导致 domainCode 为空。

2.4 解决方案

从低代码平台进入领域后调用 AI 助手。在低代码平台的工作台中先进入一个领域(如”调研问卷”),再点击 AI 助手按钮,这样 domainCode 会作为上下文参数自动传入 Agent 流程。

2.5 验证

用户从低代码平台领域内调用 AI 助手后,domainCode 正确传入(值为 RSHQ),第一个问题解决。

三、问题二:业务对象依赖顺序错误

3.1 现象

domainCode 问题解决后,AI 成功生成了业务对象和页面数据,但在「批量创建对象」节点再次报错:

CommonException: 业务对象[RS_MEMBERSHIP_CARD]不存在

3.2 分析过程

第一步:看截图,识别新错误

从截图看到错误信息变为「业务对象[RS_MEMBERSHIP_CARD]不存在」,不再是通用的”程序出现错误”,而是一个具体的业务校验错误。

判断方向:这次不是参数缺失,而是业务逻辑问题——接口在创建某个对象时,发现它依赖的另一个对象不存在。

第二步:查日志,确认调用链

docker logs hzero-aip-app --since 15m 2>&1 | grep -i "error\|RS_MEMBERSHIP\|不存在" | tail -30

找到:

ERROR --- Failed on node ...INTERNAL_INTERFACE_...
CommonException: 业务对象[RS_MEMBERSHIP_CARD]不存在

hzero-modeler 侧也确认:

Common exception, Request: {URI=/v1/0/business-objects/domain/simple-generator}
CommonException: 业务对象[RS_MEMBERSHIP_CARD]不存在

第三步:分析数据,发现依赖关系

从 aip-app 日志中提取 AI 生成的业务对象数据:

  • RS_MEMBER(会员信息):包含一个 MASTER_RELATION 类型字段 membershipCard,指向 RS_MEMBERSHIP_CARD
  • RS_MEMBERSHIP_CARD(会员卡信息):被 RS_MEMBER 引用

两个对象都是 CREATE 模式(新建),businessObjectList 中 RS_MEMBER 排在前面。

问题就在这里:批量创建时,RS_MEMBER 先被处理,它的 MASTER_RELATION 字段引用了还不存在的 RS_MEMBERSHIP_CARD,低代码平台校验依赖对象是否存在时失败。

第四步:审查脚本节点代码

用户提供了「页面&业务对象参数处理」脚本节点的完整代码。审查后发现两个问题:

  1. 没有依赖排序businessObjectList 按原始顺序传给 API,没有按 MASTER_RELATION 依赖关系排序
  2. masterBusinessObjectCode 未同步更新:脚本给 businessObjectCode 加了 domainCode 前缀(如 RSHQ_RS_MEMBER),但字段里的 masterBusinessObjectCode 没同步更新,仍指向旧编码 RS_MEMBERSHIP_CARD

3.3 根因

脚本节点缺少两个关键处理:

  1. 业务对象未按依赖关系排序,导致被引用对象排在引用者之后
  2. 加 domainCode 前缀后,MASTER_RELATION 字段的 masterBusinessObjectCode 指向了不存在的旧编码

3.4 解决方案

在脚本节点中增加两处修复:

修复 1:同步更新 masterBusinessObjectCode

在遍历 businessObjectFields 的循环中增加:

if(field.componentType === 'MASTER_RELATION' && field.masterBusinessObjectCode
   && boCodeToNewMap.has(field.masterBusinessObjectCode)) {
  field.masterBusinessObjectCode = boCodeToNewMap.get(field.masterBusinessObjectCode);
}

修复 2:拓扑排序

在 return 之前,对 businessObjectList 做 Kahn 拓扑排序:

function sortByDependency(objList){
  if(!objList || objList.length <= 1) return objList;

  var codeSet = {};
  objList.forEach(function(o){ codeSet[o.businessObjectCode] = true; });

  var deps = {};
  var inDegree = {};
  objList.forEach(function(o){
    deps[o.businessObjectCode] = [];
    inDegree[o.businessObjectCode] = 0;
  });

  objList.forEach(function(o){
    if(o.businessObjectFields){
      o.businessObjectFields.forEach(function(f){
        if(f.componentType === 'MASTER_RELATION' && f.masterBusinessObjectCode
           && codeSet[f.masterBusinessObjectCode]){
          deps[f.masterBusinessObjectCode].push(o.businessObjectCode);
          inDegree[o.businessObjectCode]++;
        }
      });
    }
  });

  var queue = [];
  objList.forEach(function(o){
    if(inDegree[o.businessObjectCode] === 0) queue.push(o.businessObjectCode);
  });

  var sorted = [];
  while(queue.length > 0){
    var code = queue.shift();
    var obj = objList.find(function(o){ return o.businessObjectCode === code; });
    if(obj) sorted.push(obj);
    deps[code].forEach(function(dep){
      inDegree[dep]--;
      if(inDegree[dep] === 0) queue.push(dep);
    });
  }

  // 循环依赖兜底
  if(sorted.length < objList.length){
    objList.forEach(function(o){
      var found = false;
      for(var i = 0; i < sorted.length; i++){
        if(sorted[i].businessObjectCode === o.businessObjectCode){ found = true; break; }
      }
      if(!found) sorted.push(o);
    });
  }

  return sorted;
}

3.5 验证

用户更新脚本节点后重新测试,业务对象和页面成功创建。

四、方法论总结:AI Agent 如何排查问题

4.1 排查框架

整个排查过程遵循一个清晰的框架:

截图/现象 → 服务状态 → 日志分析 → 参数回溯 → 代码审查 → 定位根因 → 修复验证

4.2 关键原则

原则 说明 实际应用
先看现象,不急于下结论 错误截图是最直接的信息源 第一次看到 CommonException 通用错误,不能止步于此,需要追查具体原因
服务存活先确认 排除基础设施问题 docker ps 确认容器都在运行
调用方与被调用方日志对照看 错误往往在被调用方 aip-app 抛通用异常,hzero-modeler 才有具体错误
参数回溯定位数据问题 日志中的参数数据是关键证据 从脚本节点日志中找到 domainCode=null 和 businessObjectList 的完整数据
代码审查发现逻辑缺陷 静态分析补充动态调试 审查脚本代码发现缺少排序和字段同步
一次只改一个问题 控制变量,便于验证 先修 domainCode,再修依赖顺序

4.3 工具使用策略

阶段 工具/命令 目的
服务检查 docker ps 确认容器存活状态
日志检索 docker logs --since + grep 精确过滤错误信息
参数分析 日志中的脚本节点参数输出 回溯传入接口的实际数据
代码审查 人工提供脚本源码 静态分析逻辑缺陷
修复验证 用户在平台上重新执行 端到端验证

4.4 AI Agent 的优势

在这次排查中,AI Agent 展现了几个独特优势:

  1. 多服务日志关联分析:同时查看 aip-app、aip-server、modeler 三个服务的日志,快速关联调用链,人工排查往往需要切换多个终端窗口
  2. 从海量日志中精准提取关键信息:在数万行日志中用 grep 精确定位到 3 行关键错误,避免了人工翻阅的眼疲劳
  3. 数据与代码交叉验证:从日志中提取业务对象数据结构,再对照脚本代码分析,快速发现两个缺陷
  4. 直接给出可执行的修复代码:拓扑排序算法、字段同步逻辑,不需要人工再翻译成代码

五、涉及的容器服务

服务 角色
hzero-aip-app AI 应用前端,执行 Agent 流程编排
hzero-aip-server AI 平台后端,处理 LLM 调用、知识检索
hzero-modeler 低代码建模服务,提供业务对象/页面创建 API
hzero-lowcode 低代码前端服务
hzero-lowcodedata 低代码数据服务

六、结论

两个问题的根因不同但都出在「参数传递」环节:

  1. 问题一是上下文参数(domainCode)未传入 — 需要从正确的入口调用
  2. 问题二是脚本节点对参数的处理不完整 — 缺少依赖排序和字段同步

修复后,AI 助手能够正确生成业务对象和页面,整个链路跑通。建议将脚本修复同步到产品主线版本。

HZERO 根据用户账号获取 Token 方案

问题背景

客户需求:在 HZERO 后端根据用户账号获取对应的 Token。客户原思路是”根据账号查出密码 → 解密 → 调用登录接口获取 Token”。

一、为什么”查密码→解密”方案不可行

HZERO 用户密码使用 BCrypt 单向哈希算法存储,数据库中保存的是哈希值,不可逆、不可解密。因此”从数据库查出密码 → 解密 → 调用登录接口”这条路在技术上走不通。

二、根据是否有用户明文密码,分两种方案

方案一:有用户明文密码 — 标准 OAuth2 password 模式

如果调用方持有用户的明文密码(例如用户自己输入),HZERO 原生支持标准 OAuth2 Password Grant,直接调用即可获取 Token,无需二次开发:

请求:

POST /oauth/oauth/token
Authorization: Basic <Base64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded

grant_type=password&username=用户账号&password=明文密码

返回示例:

{
  "access_token": "***",
  "token_type": "bearer",
  "refresh_token": "***",
  "expires_in": 32399999,
  "scope": "default"
}

注意事项:

  • 端点路径是 /oauth/oauth/token(两层 oauth 路径,不是 /oauth/token
  • client_idclient_secret 使用项目实际配置的客户端凭据
  • 密码传输明文,建议接口走 HTTPS
  • Token 有效期可通过 OAuth 服务端配置调整

方案二:无用户明文密码 — 自定义登录接口(二开)

如果调用方没有用户密码(例如服务间调用、管理端代操作等场景),需要在 hzero-oauth 服务中进行二次开发,实现自定义认证流程。

HZERO 已提供了标准扩展组件 LoginTokenService,核心开发步骤如下:

1. 自定义认证对象 AuthenticationToken

继承 AbstractAuthenticationToken,封装认证信息(如用户账号 + 加签字符串):

public class CustomAuthenticationToken extends AbstractAuthenticationToken {

    private final Serializable principal;  // 用户账号
    private final String sign;             // 加签字符串

    // 未认证构造方法
    public CustomAuthenticationToken(Serializable principal, String sign) {
        super(null);
        this.principal = principal;
        this.sign = sign;
        setAuthenticated(false);
    }

    // 已认证构造方法
    public CustomAuthenticationToken(Serializable principal,
            Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        this.sign = null;
        super.setAuthenticated(true);
    }

    @Override
    public Serializable getCredentials() { return null; }

    @Override
    public Serializable getPrincipal() { return this.principal; }

    public String getSign() { return this.sign; }
}

2. 自定义认证器 AuthenticationProvider

实现 AuthenticationProvider 接口,在 authenticate() 方法中:

  • 校验加签字符串(自定义安全逻辑)
  • 通过 UserDetailsService 加载用户
  • 返回已认证的 Authentication
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) {
        CustomAuthenticationToken token = (CustomAuthenticationToken) authentication;
        String username = (String) token.getPrincipal();
        String sign = token.getSign();

        // 1. 校验加签字符串(自定义安全逻辑)
        // TODO: 实现你的签名校验逻辑,例如 HMAC/RSA 验签

        // 2. 加载用户
        UserDetails user = userDetailsService.loadUserByUsername(username);

        // 3. 返回已认证的 Authentication
        return new CustomAuthenticationToken(username, user.getAuthorities());
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return CustomAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

3. 自定义 LoginTokenService

继承 LoginTokenService,在 attemptAuthentication() 中从请求提取参数:

public class CustomLoginTokenService extends LoginTokenService {

    public CustomLoginTokenService(TokenGranter tokenGranter,
            ClientDetailsService clientDetailsService,
            OAuth2RequestFactory oAuth2RequestFactory,
            CustomAuthenticationProvider authenticationProvider) {
        super(tokenGranter, clientDetailsService, oAuth2RequestFactory, authenticationProvider);
    }

    @Override
    protected Authentication attemptAuthentication(HttpServletRequest request) {
        String username = request.getParameter("username");
        String sign = request.getParameter("sign");
        return new CustomAuthenticationToken(username, sign);
    }
}

4. 配置类

@Configuration
@AutoConfigureAfter(AuthorizationServerEndpointsConfiguration.class)
public class TokenConfiguration {

    private final AuthorizationServerEndpointsConfigurer endpoints = new AuthorizationServerEndpointsConfigurer();

    @Autowired
    private List<AuthorizationServerConfigurer> configurers = Collections.emptyList();

    @PostConstruct
    public void init() {
        for (AuthorizationServerConfigurer configurer : configurers) {
            try {
                configurer.configure(endpoints);
            } catch (Exception e) {
                throw new IllegalStateException("Cannot configure endpoints", e);
            }
        }
    }

    @Bean
    public CustomLoginTokenService customLoginTokenService(
            CustomAuthenticationProvider customAuthenticationProvider) {
        return new CustomLoginTokenService(
            endpoints.getTokenGranter(),
            endpoints.getClientDetailsService(),
            endpoints.getOAuth2RequestFactory(),
            customAuthenticationProvider
        );
    }
}

5. 登录接口

@RestController
public class CustomLoginController {

    @Autowired
    private CustomLoginTokenService customLoginTokenService;

    @PostMapping("/token/custom")
    public ResponseEntity<AuthenticationResult> loginToken(HttpServletRequest request) {
        AuthenticationResult result = customLoginTokenService.loginForToken(request);
        return Results.success(result);
    }
}

调用方式:

POST /oauth/token/custom
Content-Type: application/x-www-form-urlencoded

username=用户账号&sign=加签字符串&client_id=xxx&client_secret=***

三、详细文档参考

开放平台文档《定制登录获取令牌》:

https://open.hand-china.com/document-center/doc/product/10002/11014

文档中包含完整的类图说明和短信验证码登录的代码示例,可直接参考。另外文档目录中还有《非标单点登录示例》也可作为补充参考。

更新向量模型之后如何成功重建索引

更新向量模型之后如何成功重建索引

作者:H0总助  |  文档版本:V1.0  |  适用平台:HZERO AIGC平台 1.6.1

一、引言

在HZERO AIGC平台的使用过程中,有时需要更换底层向量模型。例如原来使用的是豆包的向量模型 doubao-embedding-large-text-250515,现在要切换到阿里的 text-embedding-v4。切换完成后,文档库中已有的文档需要重建向量索引,才能让知识问答功能继续正常工作。

本文档详细记录了从切换向量模型到成功重建索引的完整操作步骤,包括过程中可能遇到的两个典型报错及其解决方法,供益吉的海森以及其他遇到类似问题的同学参考。

二、背景:为什么要换向量模型

原先系统中使用的豆包向量模型 doubao-embedding-large-text-250515 已无法使用(豆包已不再提供纯文本向量模型服务),因此需要切换到阿里的文本向量模型 text-embedding-v4。

切换流程大致如下:

在模型对接配置中新建阿里 text-embedding-v4 对接账户

在模型组合配置中创建新的向量组合(如”Jack文本向量组合-阿里”),关联阿里向量模型

在全局选项配置中,将默认文本向量模型改为新建的组合

删除旧的向量索引,然后重建

三、第一步:准备新的向量模型对接

这是最基础的一步,但有一个容易忽略的细节:向量维度。

3.1 确认向量模型的维度

不同的向量模型输出的向量维度是不同的:

向量模型输出维度说明
doubao-embedding-large-text-2505152048豆包旧版纯文本向量模型,已停止服务
text-embedding-v4(阿里)1024阿里当前最新文本向量模型
doubao-embedding-vision(豆包)多种可选豆包新版图文向量模型

如果你的旧索引是用 2048 维度建的,现在换成了 1024 维度的模型,那重建索引时就会报错(见第五节)。

3.2 在值集中添加新维度(如果需要的话)

新建模型对接账户时,当你选择了”向量-阿里”这个模型类型后,系统要求你选择一个维度值。如果下拉菜单中找不到 1024 这个选项,说明值集中没有这个维度的配置。

操作路径:

系统管理 > 值集管理 > 搜索”向量模型维度”(或类似名称) > 在值集值列表中添加一条新记录,值填写 1024,含义填写”阿里向量模型维度”或其他便于识别的名称。

添加完成后回到模型对接配置页面,刷新后 1024 就会出现在下拉选项中了。

3.3 新建模型对接账户

在”模型对接配置”页面,点击”新建”按钮,填写以下信息:

字段填写内容说明
账户编码JACK-TEXT-EMBEDDING-ALI自定义,建议有意义的命名
模型分类向量-阿里选择阿里文本向量模型分类
模型类型text-embedding-v4选择对应的阿里模型
维度1024选择刚添加到值集中的维度
ak/sk等凭证根据实际情况填写阿里云的API访问凭证

配置完成后点击”测试”按钮,确认返回正确的向量值,表示对接成功。

3.4 创建新的模型组合

在”模型组合配置”页面,点击”新建”:

– 组合名称:例如 “Jack文本向量组合-阿里”

– 模型角色:文本向量

– 策略选择:轮询(如果有多个模型需要均衡)或优先级

– 关联模型:选择刚才新建的阿里向量模型对接账户

创建完成后点击”测试”,验证组合可用。

3.5 设置为默认文本向量模型

在”全局选项配置”页面,找到”默认文本向量模型”配置项:

点击编辑,将原来的默认向量组合改为刚创建的”Jack文本向量组合-阿里”

保存并确认弹窗

四、第二步:清理旧索引并重建

换了向量模型后,旧的索引映射(mapping)依然保持着旧模型的维度设定(如2048),与新模型(1024)不匹配。因此需要清理旧索引,让系统重新创建。

4.1 查看并释放旧索引

在”向量库集合管理”页面,可以看到所有已有的索引,通常包括:

haip_doc_chunks_0 文档索引

haip_question_index_0 问题索引

haip_dictionary_value_0 词典索引

haip_feature_word_0 特征词索引

haip_summary_index_0 摘要索引

逐个点击操作列的”释放”按钮释放索引。释放后索引会出现在底部列表中,再点击”删除”彻底移除。注意:释放和删除是两步操作,缺一不可。

4.2 检查文档同步状态

清理索引后,导航到”文档库管理”页面,你会发现文档的”状态”列仍然显示”已同步到向量库”或”已同步到ES”。这是因为文档表中记录的状态缓存未被清理。重新同步时会自动更新状态,不影响后续操作。

4.3 执行同步

在文档库管理页面,可以选中一个或多个文档,点击”同步处理” > “选择同步” 进行单文档测试,或点击”全部同步”批量重建索引。系统会重新读取文档内容、切片、调用向量模型生成embedding并写入新的ES索引。

五、常见问题一:向量维度不匹配(Failed: X document(s) failed to index)

5.1 错误现象

在执行文档同步时,右下角弹出红色错误提示:

“资源同步失败 – 内容同步(向量库) – Failed: 10 document(s) failed to index.”

点开文档的同步信息详情,可以看到更具体的错误:

“The [dense_vector] field [embedding] in doc … has a different number of dimensions [1024] than defined in the mapping [2048].”

5.2 原因分析

ES向量索引的mapping中预定义的向量维度是2048(来自原来的豆包模型),但新模型阿里 text-embedding-v4 输出的向量维度是1024。写入时维度不一致,ES拒绝写入。

5.3 解决方法

按照第四节的步骤,在值集中添加1024维度 → 新建维度为1024的模型账户 → 新建组合 → 设为默认 → 删除旧索引 → 重建同步。新索引创建时会自动按新模型维度建立mapping。

⚠️ 关键注意点:向量维度一旦在模型对接账户中配置,后续不可修改。如果要换维度,只能新建一个模型对接账户,不能编辑原有的。

六、常见问题二:PDF图片识别失败(调用HKMS执行文件切片时发生错误)

6.1 错误现象

执行同步后,右下角弹出错误提示:

“调用HKMS执行文件切片时发生错误: I/O error on POST request for http://hzero-hkms:18080/kms/loader/v2/process_file: Timeout”

或:

“调用HKMS执行文件切片时发生错误: Failed: 67/19 document(s) failed to index.”

查看hzero-hkms容器日志,会发现大量WARNING级别的报错:

“response from Hzero API: {failed: True, code: haip.error.arrange.account_config.not_exists, message: ‘模型{0}不可用,请重新选择其他模型。’}”

6.2 原因分析

这个错误的根本原因不是向量模型的问题,而是PDF处理流程中的一个关键环节:

HKMS在执行文档切片(process_file)时,对于PDF文件中的图片,需要调用一个多模态大模型来解释图片内容(图片说明/OCR)。这个图片识别走的是”全局选项配置”中的”图片识别模型”配置,而不是”默认对话模型”。

如果你的”图片识别模型”组合中配置了已下架或不可用的模型(例如kimi-2.5已下架),图片识别就会失败,进而导致整个文档切片处理异常并超时。

6.3 解决方法

步骤1:在”模型组合配置”中找到当前配置为”图片识别模型”的那个组合。

步骤2:检查该组合中包含的模型是否都可用(特别是有没有已经下架的模型)。

步骤3:如果某个模型已不可用,在组合中禁用它或切换到其他可用的模型(例如doubao-seed-1.8)。

步骤4:重新测试组合是否可用(点击测试按钮)。

步骤5:确认”默认对话模型”不需要修改,可以继续保持使用纯文本对话模型(如deepseek-V3),因为”图片识别模型”是独立配置的,两者互不干扰。

步骤6:重新执行文档同步(选择同步或全部同步)。

七、完整操作流程一览

以下是更换向量模型后、重建索引成功的完整操作流程,按顺序执行即可:

序号步骤操作位置说明
1确认新模型的向量维度模型文档/阿里官网例如阿里 text-embedding-v4 = 1024 维
2值集中添加新维度(如需)值集管理 > 向量模型维度如果维度选项不存在,先添加
3新建模型对接账户模型对接配置选择模型分类、类型、维度
4新建模型组合模型组合配置关联刚建的模型账户
5设为默认文本向量模型全局选项配置修改默认文本向量模型配置项
6检查图片识别模型是否可用模型组合配置若有已下架模型,更换或禁用
7释放并删除旧向量索引向量库集合管理逐条释放后再删除
8执行文档同步文档库管理选”选择同步”测试或”全部同步”批量
9验证知识问答功能AI对话/知识问答确认能正确检索文档内容

备注:向量模型更改后,原来的向量索引被全部删除,除了文档索引需要重建外,
Agent词典、Agent编排的唤醒词 也要向量同步,否则回导致智能导航和多Agent应用唤醒Agent不可用。

八、避坑指南与关键要点

8.1 关于向量维度

向量维度一旦在模型对接账户中配置,后续不可修改

如需更改维度,只能新建一个模型对接账户

新建账户时如果维度选不到,先去值集管理中添加

同一个向量模型可能有多个维度版本,务必确认正确的值

8.2 关于模型组合中的已下架模型

AI模型厂商经常下架旧版本模型,下架后虽然账户还在,但实际调用会失败

检查模型组合时,不仅要看是否有模型,还要看模型是否仍然可用

如果一个组合中有多个模型,其中一个不可用会导致整个组合失败吗?取决于策略配置。轮询策略下如果轮询到已下架模型就会失败,建议禁用或移除已下架的模型。

8.3 关于图片识别模型的独立配置

PDF中的图片识别走的是”图片识别模型”配置,不是”默认对话模型”

这意味着你可以在对话中使用纯文本模型(如DeepSeek-V3),同时使用多模态模型处理PDF图片

两者互不干扰,不需要为了文档同步而修改默认对话模型

8.4 排查思路总结

如果文档向量索引重建失败,建议按以下顺序排查:

第一步:查看hzero-hkms的容器日志,找到具体的错误信息

第二步:如果是”dimensions mismatch”相关错误,检查向量维度是否匹配

第三步:如果是”file切片超时”或”model not exists”相关错误,检查图片识别模型的配置

第四步:修复后重新执行同步测试

九、总结

更换向量模型后重建索引,本质上是处理两个层面的问题:一是”数据格式”层面——新模型输出的向量维度与旧索引mapping不一致;二是”模型调用”层面——图片识别依赖的模型是否可用。

两个问题都解决后,文档向量索引重建和知识问答功能就能正常工作。希望本文能帮助你在遇到类似问题时,更快地定位和解决问题。

—END—

附图:

HZERO PaaS平台-Docker版demo笔记(五)安装部署readme

最新更新:2026/07/04

本文是HZERO PaaS平台-Docker版Demo 实验环境的readme文件

说明:本实验环境版本仅供个人测试用,企业开发、测试、正式环境不要用,企业用平台可参考汉得开放平台上各产品的官方文档去安装。

HZERO PaaS 平台介绍:

HZERO 是汉得企业级 PaaS平台, 本HZERO PaaS 平台 R12 Demo实验环境 Docker版  是基于汉得HZERO 基础开发平台1.12.2.RELEASE、流程平台1.20.0-1.12.RELEASE版、低代码平台2.10.0-1.12.RELEASE版、集成平台1.8.1.RELEASE,AI平台 1.6.1.ALPHA.7.1 版本组装而成。

一、安装准备-下载文件:

先下载文件:

百度网盘分享的文件:hzero-demo-docker-openJ9

链接: https://pan.baidu.com/s/1atCVvaDxlR2LHhixVo3Q0Q?pwd=Hand  提取码: Hand (下载镜像压缩包目录和持久化数据压缩包文件,大小约24G, 建议使用百度网盘SVIP会员下载大约20分钟。普通用户则会非常慢(100K/秒),没有也不想申请短期百度网盘SVIP会员的用户可考虑用阿里云快传下载,速度稍快(大概1M/秒),缺点是只有一天有效期,请联系作者索要临时的阿里云快传链接。)

需下载文件说明(x86的Cpu用户,在x86目录下):

  1. Docker镜像包目录:hzero-docker-images,包含所有服务的Docker镜像。
  2. 持久化数据压缩包文件:hzero-dockers.tar.gz,包括数据库文件、配置文件、启停服务脚本。

备注:如果使用基于M系列芯片的Mac电脑用户,CPU架构是arm64的,请下载对应的arm版文件:

下载 hzero-docker-images-arm64目录 替代hzero-docker-images目录

下载 hzero-dockers-arm64.tar.gz 替代hzero-dockers.tar.gz

Arm版 Mac电脑在安装时,需要注意 Docker默认分配内存比较小,会导致服务起不来或者非常慢,请提前分配好Docker的内存到25G(跑全部服务)或者11G(仅跑精简版基础开发平台+低代码平台)


二、安装准备:Docker环境

先安装Docker 和Docker compose

安装场景:

1.1 如果你是直接在linux平台上安装,先安装Docker 再装docker compose

安装方法:请在豆包中输入:“请给我 linux 上先装Docker 再装 新版Compose 的操作步骤”

然后按豆包给出步骤操作即可。

备注:务必安装新版的docker compose, 重点

老版本:指 docker-compose(v1 系列),基于 Python 开发的独立命令行工具,命令是: docker-compose
新版本:指 docker compose(v2 系列),基于 Go 语言重构的 Docker CLI 插件,命令是:docker compose
新版本(v2)在权限处理逻辑上更贴合 Docker 原生行为,老版本(v1)因架构问题易出现权限不一致的情况。
权限问题的核心根源:

Docker Compose 本身不直接控制 “容器内用户权限”,而是负责解析配置、调用 Docker 引擎创建容器;权限最终由 Docker 引擎决定,但新老版本的调用方式 / 时机不同,导致了权限表现的差异:
老版本(v1,Python 实现):docker-compose 是独立 Python 进程,创建挂载目录时,会以宿主机执行 docker-compose 命令的用户(通常是 root / 当前普通用户)权限在宿主机创建目录,而非容器内指定的用户。比如:容器内用 user: 1000:1000 运行,但宿主机的挂载目录会被 docker-compose 以 root 权限创建(权限 755,属主 root:root),容器内 1000 用户可能无法写入。

新版本(v2,Go 实现):docker compose 作为 Docker CLI 插件,直接调用 Docker 引擎的 API,挂载目录的创建逻辑完全交给 Docker 引擎处理—— 而 Docker 引擎会根据容器内指定的 user/group 适配权限(或保持与宿主机一致),更符合开发者预期。


1.2 如果你是在windows上使用WSL, 那么直接安装Docker Desktop(包含Docker引擎和Docker compose, 且为可视化管理),然后再做WSL跟Docker Desktop的集成即可(在Docker Desktop的右上角的Setting齿轮/Resoures/WSL intergration 处把要集成的WSL开关设置为开 )

安装方法:请在豆包中输入:“请给我Windows安装Docker Desktop 的操作步骤”

然后按豆包给出步骤操作即可。

安装完成后做WSL跟Docker Desktop的集成。

说明:WSL是windows的linux子系统,如果不知道如何启用WSL,请在豆包中输入:“请给我在Windows中启用WSL的操作步骤”

然后按豆包给出的步骤操作即可。

三、加载Docker镜像

以root用户 操作:

进入 hzero-docker-images目录,运行load-dockers.sh脚本,完成所有服务镜像的加载

$ cd  hzero-docker-images

$ bash load-dockers.sh

四、启动/关闭平台服务

在linux系统下,解压缩 持久化数据压缩包文件 ,例如:

tar -xzvf hzero-dockers.tar.gz

备注:务必在linux系统下解压,这样可以保留目录权限,不要在windows目录下解压再拷贝到linux,会因为权限问题报错。

启动HZERO PaaS平台(基础开发平台+低代码平台+集成平台+AI平台)服务:

$ cd hzero-dockers

$ bash start-all-dockers.sh

#全部服务启动完成大约需要12分钟,内存消耗25G(笔记本电脑环境,如果是Windows上的WSL虚拟机,考虑windows本身还需要消耗7-8G,那么32G内存笔记本启动 HZERO PaaS平台 是够用的)

#备注:Mac电脑Arm 版CPU用户首次启动时会从dockerHub官方下载mongo,redis,nginx,elasticsearch,neo4j,onlyoffice 这几个Docker镜像,时间会稍长,请耐心等待并保持网络畅通

关闭平台服务:

$ cd hzero-dockers

$ bash stop-all-dockers.sh

#备注:如果要 单启动HZERO基础开发平台+低代码平台可以:
$ cd hzero-dockers
$ bash lowcode-all-dockers-start.sh
关闭服务:
$ bash lowcode-all-dockers-stop.sh

#备注:如果要 单启动HZERO基础开发平台+AI平台可以:
$ cd hzero-dockers
$ bash ai-all-dockers-start.sh
关闭服务:
$ bash ai-all-dockers-stop.sh

五、访问系统

在windows host文件添加解析:

假设你 的服务器IP是 172.18.14.48

172.18.14.48 dev.hzero.com.cn #Nginx服务器地址
172.18.14.48 gateway.hzero.com.cn # 网关的地址
172.18.14.48 aigc.hzero.com.cn # AIGC服务的反向代理
172.18.14.48 kkv.hzero.com.cn # 文件预览服务域名
172.18.14.48 oss.hzero.com.cn # minio文件服务域名
172.18.14.48 onlyoffice.hzero.com.cn # onlyoffice文档在线编辑服务

完成hosts设置户,访问http://dev.hzero.com.cn

用户名/密码: admin/Admin@123!

5.1 看低代码平台Demo

选择低代码POC演示租户 ,进入系统后点右上角的“前往控制台”,然后点左上角菜单,选择菜单”POC演示-知识产权管理” ,可以看到一个低代码搭建的关于知识产权管理的应用.

选择菜单“低代码平台”,进入低代码工作台,可进行低代码开发;

低代码POC演示-知识产权管理

低代码工作台:

进入低代码平台 菜单,接下来你可以 进行低代码开发了。 学习文档和视频可以看汉得开放平台的学习路线:

开放平台网址:open.hand-china.com

视频路径: 开放平台/社区与合作伙伴/视频与培训/学习路线/飞搭平台学习路线  

从初级开始学习

5.2 看AI平台demo

切换租户,选择HZERO 平台租户 ,进入系统后点右上角的“前往控制台”,然后点左上角菜单,进入AIGC中台/模型管理中心/模型对接配置

点击右上角三个小点点,切换到平台租户:

然后点击右上角“前往控制台”,切换到传统菜单

进入AIGC中台/模型管理中心/模型对接配置

5.2.1、设置jack对话-deepseek-V4-flash,Jack文本向量-阿里2,Jack-图文向量-豆包 ,Jack重排模型-阿里,这四个模型的API Key

5.2.1.1 你需要预先在火山引擎注册账号 https://www.volcengine.com/, 然后从主页 /大模型 进入,然后选择左边的“开通管理”菜单,找到deepseek-v4-flash-260425,doubao-embedding-vision-250615,doubao-seed-2-0-mini-260428 这三个模型,点操作“开通服务”

5.2.1.2 在火山引擎/火山方舟 左边菜单 API key管理 处,复制API-KEY

然后把获取的API Key 填入:

5.2.2、设置 Jack重排模型-阿里 , 和 Jack文本向量-阿里-2 的API Key

5.2.2.1 你需要预先在阿里云注册账号 ,然后在主页/大模型/免费体验 进入阿里云百炼平台,然后点左下角的密钥管理可获取API Key

然后把获取的API Key填入:

2.3、看AI平台demo

选择HZERO 平台租户 ,进入系统后点左上角菜单,进入AIGC中台/应用中心/企业应用库, 点击进入“我的HZERO运营知识库”, 可以咨询Hzero平台相关问题,比如 :你可以问:“飞搭会用到AI平台功能吗?”


重要提醒:

1、现在这个版本用的IBM OpenJ9的JVM , 是内存节省优先的,32G内存的笔记本可以跑所有服务。

2、如果你内存很大,比如有64G,要性能优先的: 可以用OpenJDK标准的HotSpot JVM , 这个版本内存消耗较大,HostSport JVM版本的下载地址:

https://pan.baidu.com/s/1cqL199Cl_61qpAANo8pnwA?pwd=Hand      提取码: Hand 文件大小:18.31G, 使用百度超级会员下载大约20分钟

备注: 这个Demo版本主要用于个人学习,以适应40G以内的笔记本为主要目标,所以,OpenJDK标准的HotSpot JVM , 这个版本 在2026年之后就不再维护了。

3、如果你只有16G内存的笔记本,也想把HZERO平台部署跑起来,请参考

Jack.Shang的技术博客 » HZERO PaaS平台组装笔记十五-使用IBM OpenJDK_OpenJ9 第四部分: 16G笔记本运行方案

4、关于docker版实验Demo环境系列笔记可参考:

http://blog.retailsolution.cn/archives/category/hzero/hzero-docker%e7%89%88

5、有关本Demo系统的更新日志可参考:
Jack.Shang的技术博客 » HZERO PaaS平台-Docker版 -更新日志

H-ZERO DevPaaS微服务开发平台的服务+插件架构设计

在“服务 + 插件”架构中,平衡服务与插件的发展,需从规划、开发、管理与评估等多方面着手:
1. 前期规划
– **明确主次与边界**:清晰界定服务和插件的核心功能与职责。服务应提供稳定、基础的功能框架,像电商系统的用户管理、订单处理服务,保障系统基本运作;插件则侧重于拓展和个性化定制,如个性化推荐插件、营销活动插件。避免功能重叠,确保二者相辅相成。
– **制定协同发展路线图**:结合业务战略,规划服务与插件的长期发展路径。明确不同阶段服务升级与插件开发计划。例如,在新业务拓展初期,先完善基础服务,随后围绕新业务开发相关插件,实现二者有序推进。
2. 开发过程
– **遵循统一标准**:建立统一的技术标准和接口规范,确保服务与插件间无缝对接。如规定统一的数据格式、通信协议,无论服务还是插件开发,都依此标准,降低集成难度,提高兼容性与可维护性。
– **保障兼容性**:服务升级时,充分考虑现有插件兼容性,避免接口或数据结构变动致插件失效。同样,插件开发也应适配服务的当前与未来版本。可通过版本管理和兼容性测试机制,如语义化版本号,确保二者协同演进。
– **促进双向反馈**:开发服务与插件的团队保持紧密沟通。服务团队及时向插件团队通报服务架构、接口变化;插件团队反馈插件开发中遇的问题与需求,助服务团队优化设计,实现协同优化。
3. 管理与维护
– **资源合理分配**:依据业务需求与发展阶段,合理分配人力、物力资源。若某阶段重点拓展服务功能,适当增加服务开发资源;若需丰富插件生态,侧重插件开发投入,确保资源与发展重点匹配。
– **建立测试与监控体系**:构建全面测试机制,涵盖单元测试、集成测试、功能测试等,确保服务与插件功能正常及协同工作稳定。同时,搭建监控系统,实时监测性能指标,如响应时间、资源利用率,及时发现处理问题。
– **版本管理与发布协调**:规范服务与插件版本管理,确保版本对应清晰。发布新版本时,协调发布时间与内容,提前通知相关方,做好升级准备与过渡,降低对业务影响。
4. 评估与优化
– **收集用户反馈**:通过多种渠道收集用户对服务与插件的反馈,了解使用体验、需求与问题。如设置用户反馈渠道、开展用户调研,依据反馈优化服务与插件功能。
– **定期评估**:定期评估服务与插件发展情况,对比规划目标,分析进展与偏差。采用关键指标评估,如服务稳定性、插件使用率、用户满意度等,据此调整发展策略。
– **持续优化**:基于评估结果与用户反馈,持续优化服务与插件。对服务性能瓶颈优化,对插件功能改进拓展,使二者不断适应业务发展与用户需求。