You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Boto3的retrieve_and_generate函数实现AWS Bedrock知识库的日期范围过滤(基于OpenSearch)

如何配置Boto3的retrieve_and_generate函数实现AWS Bedrock知识库的日期范围过滤(基于OpenSearch)

我之前在使用Bedrock的retrieve_and_generate搭配OpenSearch知识库做日期过滤时,也踩过几乎一模一样的坑!核心问题出在日期值的类型和格式传递上,尤其是你遇到的浮点数科学计数法解析错误,其实是boto3序列化大整数时的默认行为导致的。下面给你分享我实测有效的解决方案:

核心问题分析

你尝试用epoch毫秒的时候,OpenSearch报错无法解析1.6015104E12,这是因为当你把epoch毫秒转成整数后,boto3在把请求序列化成JSON时,会把超过一定大小的整数自动转换成浮点数(用科学计数法表示),而OpenSearch的epoch_millis格式只接受整数类型的毫秒数,自然就解析失败了。

而用字符串日期的时候如果报错,大概率是你传递的格式没有匹配OpenSearch默认支持的日期格式(默认是strict_date_optional_time||epoch_millis,完美兼容ISO 8601标准格式)。

最优解决方案:用ISO 8601标准字符串传递日期

直接使用UTC时区的ISO 8601格式字符串(比如2024-01-30T00:00:00Z)是最稳妥的方式,既不需要担心类型转换问题,OpenSearch也能完美解析。

步骤1:修改日期处理代码

把你Lambda函数里的日期转换逻辑改成直接生成标准ISO 8601字符串,替换原来的epoch毫秒转换:

import datetime
from datetime import timezone

def lambda_handler(event, context):
    # ... 其他原有代码 ...
    filters = []
    pub_date_gte = body.get('publication_date_gte')
    pub_date_lte = body.get('publication_date_lte')

    # 处理起始日期
    if pub_date_gte:
        try:
            # 兼容两种输入格式:yyyy-MM-dd 或者 带时区的ISO字符串(比如2024-01-30T12:00:00Z)
            if 'Z' in pub_date_gte or '+' in pub_date_gte:
                # 处理带时区的输入
                pub_date_obj = datetime.datetime.fromisoformat(pub_date_gte.replace('Z', '+00:00'))
            else:
                # 处理yyyy-MM-dd格式,默认转成UTC的0点
                pub_date_obj = datetime.datetime.strptime(pub_date_gte, '%Y-%m-%d').replace(tzinfo=timezone.utc)
            # 生成标准ISO 8601字符串(带Z后缀)
            pub_date_gte_str = pub_date_obj.isoformat().replace('+00:00', 'Z')
            filters.append({
                "greaterThanOrEquals": {
                    "key": "effective_date",  # 对应你OpenSearch里的日期字段名
                    "value": pub_date_gte_str
                }
            })
        except ValueError as e:
            print(f"无效的日期格式:{e}")
            # 可以根据需求添加错误处理逻辑

    # 处理结束日期(同理)
    if pub_date_lte:
        try:
            if 'Z' in pub_date_lte or '+' in pub_date_lte:
                pub_date_obj = datetime.datetime.fromisoformat(pub_date_lte.replace('Z', '+00:00'))
            else:
                pub_date_obj = datetime.datetime.strptime(pub_date_lte, '%Y-%m-%d').replace(tzinfo=timezone.utc)
            pub_date_lte_str = pub_date_obj.isoformat().replace('+00:00', 'Z')
            filters.append({
                "lessThanOrEquals": {
                    "key": "effective_date",
                    "value": pub_date_lte_str
                }
            })
        except ValueError as e:
            print(f"无效的日期格式:{e}")

    # 组合过滤器(原有逻辑保留)
    if filters:
        chat_filter = {"andAll": filters}
    else:
        chat_filter = {}
    # ... 后续调用retrieve_and_generate的代码 ...

步骤2:确认OpenSearch的日期字段映射

确保你的OpenSearch索引中,effective_date字段的类型是date(默认的日期格式就包含strict_date_optional_time,所以不需要额外修改映射,除非你自定义了格式)。你可以通过OpenSearch的Dev Tools执行以下命令确认:

GET bedrock-knowledge-base-default-index/_mapping/field/effective_date

返回结果里应该显示type: "date",并且format包含strict_date_optional_time。

为什么不用epoch毫秒?

如果你坚持要用epoch毫秒,需要解决boto3的浮点数序列化问题:你可以尝试把epoch毫秒转成字符串?不行,因为OpenSearch的epoch_millis要求数值类型。另一种方法是确保boto3把整数序列化成整数而不是浮点数,但这需要修改boto3的序列化配置,操作起来比较麻烦,不如直接用ISO字符串省心。

验证过滤器结构

最后再确认你的过滤器结构是正确的,比如多个条件用andAll组合,单个条件用greaterThanOrEquals/lessThanOrEquals,布尔、字符串过滤的逻辑你已经能正常使用,所以只要日期值的格式对了,整个过滤器就能正常工作。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 09:24:36