资讯动态

基于阿里云服务构建Agentic Lake:打通AI智能体与业务数据鸿沟的实践指南

发布时间:2026/8/20 14:43:26 来源:尧图企业网站定制
在实际 AI 应用开发中一个长期困扰开发者的核心问题是大模型本身能力强大但如何让它稳定、可靠地访问和处理我们自己的业务数据直接让模型读取数据库或文件不仅面临格式混乱、权限失控的问题更难以保证数据的一致性和时效性。数据与智能体之间的鸿沟成为了 AI 应用落地的关键瓶颈。阿里云提出的Agentic Lake概念正是为了解决这一痛点。它并非一个独立的产品而是一种面向 AI 智能体AI Agent的数据架构理念和最佳实践集合。其核心目标是构建一个“为 AI 智能体就绪”的数据湖让数据能够以智能体易于理解和高效利用的方式被组织、管理和服务。简单来说它试图回答当你的智能体需要数据时应该从哪里、以何种格式、通过什么协议安全地获取。本文将深入解析 Agentic Lake 的核心思想并提供一个从零开始的实践指南。我们将以一个“智能客服知识库问答”场景为例演示如何基于阿里云现有服务如 OSS、DataWorks、MaxCompute、Flink 等搭建一个符合 Agentic Lake 理念的数据底座并最终通过一个 Spring AI 应用来消费这些数据。无论你是数据工程师、后端开发者还是 AI 应用架构师理解这套方法论都将帮助你更系统地设计 AI 时代的数据基础设施。1. 理解 Agentic Lake为什么传统数据湖对 AI 不“友好”在深入实践之前必须厘清 Agentic Lake 要解决的根本问题。传统数据湖Data Lake以存储原始数据为中心强调“存得下、存得全”但其数据组织方式如按日期分区的 Parquet 文件和访问接口如 Hive SQL、Spark Job主要是为批处理分析和数据科学家设计的。当 AI 智能体需要数据时这种模式会暴露诸多问题数据发现困难智能体无法像人类一样通过表名和字段注释来理解数据含义。它需要的是语义化的元数据例如“这是一份2023年华东地区的用户订单表包含商品ID、购买时间和金额”。访问延迟高批处理作业动辄分钟级延迟无法满足智能体实时或近实时交互的需求。智能体期望毫秒到秒级的响应。格式不兼容存储在数据湖中的二进制格式Parquet、ORC或复杂嵌套结构不能直接作为大模型的输入。模型需要的是结构清晰、长度适中的自然语言或 JSON 片段。权限与安全传统的库表级权限控制过于粗放智能体可能需要访问多张表的特定列组合且每次访问都应有审计日志。数据新鲜度智能体需要的是最新状态的数据而传统 T1 的数据同步链路无法满足。Agentic Lake 的核心理念是“以智能体为中心重构数据流水线”。它要求数据湖具备以下关键特征语义化层在原始数据之上构建一个机器可读的、富含业务语义的元数据层。实时化服务提供低延迟的数据查询与服务化接口如 GraphQL、gRPC API而非仅支持批处理作业。向量化就绪原生支持将非结构化数据文本、图像转换为向量嵌入Embeddings并建立高效的向量索引便于智能体进行语义检索。治理与安全细粒度的数据访问控制、完整的审计追踪以及数据血缘确保智能体的每次数据调用都在监管之下。2. 环境准备与核心服务选型在阿里云生态中我们可以组合多个服务来构建一个符合 Agentic Lake 理念的架构。以下是本次实践的环境清单与选型说明。2.1 基础环境与工具准备首先确保你拥有以下基础环境阿里云账号拥有一个实名认证的阿里云账号并确保账户余额或资源包充足。本地开发环境JDK 8 或 11推荐 11。Maven 3.6 或 Gradle。IDE如 IntelliJ IDEA 或 VS Code。Git。命令行工具阿里云 CLI用于管理云资源。安装后需执行aliyun configure进行密钥配置。# 安装阿里云 CLI (以 macOS 为例) curl -O https://aliyuncli.alicdn.com/aliyun-cli-macosx-latest-amd64.tgz tar -xzvf aliyun-cli-macosx-latest-amd64.tgz sudo cp aliyun /usr/local/bin/ # 配置访问密钥 (AccessKey ID 和 Secret) aliyun configure2.2 阿里云服务清单与角色我们将使用以下阿里云服务请提前在控制台开通。注意记录每个服务的实例 ID、Endpoint 和必要的连接信息如 Bucket 名称、Project 名称。服务用途关键配置项对象存储 OSS存储原始的非结构化数据如产品手册 PDF、客服对话日志 TXT。Bucket 名称、Endpoint、读写权限RAM Policy。大数据开发治理平台 DataWorks作为数据开发和调度的中心编排数据同步、清洗和语义化任务。工作空间 ID、业务流程。实时计算 Flink处理实时数据流将业务系统的变更实时同步到服务层。集群 ID、作业 Jar 包部署。云原生数据仓库 AnalyticDB MySQL作为实时服务化层存储结构化的、高并发的业务数据供智能体低延迟查询。集群连接地址、数据库名、账号密码。云原生数据湖分析 DLA可选用于对 OSS 上的数据执行即席查询补充分析能力。Serverless 端点。人工智能平台 PAI提供向量生成模型和向量检索服务用于处理非结构化文本。模型服务地址、API Key。注意在生产环境中务必通过 RAM资源访问管理创建子账号并授予最小必要权限避免使用主账号 AccessKey。2.3 项目初始化与 Maven 配置我们将创建一个 Spring Boot 项目作为智能体应用。使用 Spring Initializr 或 IDE 创建项目核心依赖包括 Spring Web、Spring AI用于接入大模型和数据库驱动。由于 Spring AI 和部分阿里云 SDK 可能不在默认仓库需要在pom.xml中配置阿里云 Maven 镜像仓库以加速依赖下载。project !-- ... 其他配置 ... -- repositories repository idaliyunmaven/id name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url releases enabledtrue/enabled /releases snapshots enabledfalse/enabled /snapshots /repository !-- 如果需要 Spring 官方快照库可额外添加 -- /repositories dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Spring AI 依赖以 OpenAI 为例 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId version0.8.1/version !-- 请使用最新稳定版 -- /dependency !-- 阿里云 OSS SDK -- dependency groupIdcom.aliyun.oss/groupId artifactIdaliyun-sdk-oss/artifactId version3.17.4/version /dependency !-- MySQL 驱动用于连接 AnalyticDB MySQL -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency !-- 其他工具依赖如 Lombok -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies !-- ... 其他配置 ... -- /project3. 构建 Agentic Lake 数据底座从原始数据到智能体就绪我们的目标是当智能客服被问到“你们最新款的智能手机有什么颜色”时它能从产品库中准确找到信息并回答。下面分步构建数据流水线。3.1 原始数据入湖与标准化存储假设原始数据来源有两个业务数据库产品信息表products存储在自建 MySQL 中。非结构化文档产品详细说明书 PDF存放在本地。步骤一将业务数据同步至 OSS作为原始备份使用 DataWorks 的数据集成功能将 MySQL 的products表全量及增量同步到 OSS 的一个指定路径下格式为 Parquet。这步的目的是建立原始数据备份并统一存储位置。在 DataWorks 中创建一个“数据同步”节点关键配置如下数据源配置 MySQL 数据源连接。目标源配置 OSS 数据源连接。同步任务配置{ job: { content: [{ reader: { name: mysqlreader, parameter: { username: db_user, password: your_password, column: [id, name, category, attributes, update_time], splitPk: id, connection: [{ table: [products], jdbcUrl: [jdbc:mysql://rm-xxx.mysql.rds.aliyuncs.com:3306/product_db] }] } }, writer: { name: osswriter, parameter: { bucket: your-agentic-lake-bucket, endpoint: oss-cn-hangzhou.aliyuncs.com, objectPrefix: raw/mysql/products/, // 按日期分区可追加 ${bdp.system.bizdate} fileFormat: parquet, writeMode: overwrite // 或 append根据策略定 } } }] } }调度此任务为每日全量或每小时增量。步骤二将非结构化文档上传至 OSS使用阿里云 OSS SDK 或控制台将产品说明书 PDF 上传到 OSS 的另一个目录。# 使用阿里云 CLI 上传文件 aliyun oss cp /local/path/product_manual.pdf oss://your-agentic-lake-bucket/raw/docs/3.2 构建语义化与实时服务层原始数据无法被智能体直接使用我们需要将其加工成“就绪”状态。步骤一结构化数据服务化目标是将products表的数据提供毫秒级查询的 API。实时同步使用 Flink CDC 连接 MySQL实时捕获products表的变更Insert, Update, Delete并写入AnalyticDB MySQL。-- 在 AnalyticDB MySQL 中创建目标表 CREATE TABLE products_serving ( id BIGINT PRIMARY KEY, name VARCHAR(255), category VARCHAR(100), attributes JSON, -- 使用 JSON 类型存储灵活的属性如颜色、内存 update_time TIMESTAMP, INDEX idx_category (category) );Flink Job 逻辑编写 Flink SQL 作业将 CDC 流中的数据直接UPSERT到products_serving表。这样AnalyticDB MySQL 中就始终保持着产品的最新状态。步骤二非结构化数据向量化目标是将产品说明书 PDF 中的文本内容转换为向量支持语义检索。文本提取使用 DataWorks 的 PyODPS 节点或一个独立的 ECS 任务调用 PDF 解析库如pdfplumber提取 OSS 中 PDF 的文本内容。文本分块将长文本按段落或固定长度切分成片段Chunks。向量生成调用PAI 的向量生成模型服务或使用开源模型如text2vec将每个文本片段转换为向量。向量存储将(文本片段, 向量, 元数据如来源PDF、页码)写入支持向量检索的数据库如阿里云Elasticsearch具备向量检索插件或Hologres。这里以在 DataWorks 中调用 PAI 服务为例伪代码# 在 DataWorks PyODPS 节点中 from odps import ODPS import requests import json # 读取提取后的文本块 texts [...] # 文本块列表 # 调用 PAI-EAS 部署的向量模型服务 def get_embedding(text): url https://your-pai-eas-endpoint/predict headers {Authorization: your-token} resp requests.post(url, json{text: text}, headersheaders) return resp.json()[embedding] vectors [get_embedding(t) for t in texts] # 将文本和向量写入 Elasticsearch (需安装对应客户端) from elasticsearch import Elasticsearch es Elasticsearch([your-es-endpoint]) for i, (text, vec) in enumerate(zip(texts, vectors)): doc { text: text, embedding: vec, source: product_manual_v1.pdf, chunk_id: i } es.index(indexproduct_docs, idi, documentdoc)3.3 构建统一的元数据与数据目录这是 Agentic Lake 的“大脑”。我们需要一个地方告诉智能体“关于产品规格你可以去查 AnalyticDB MySQL 的products_serving表关于产品使用细节你可以去product_docs向量索引里做语义搜索。”我们可以用一个简单的 MySQL 表或配置文件来维护这个目录CREATE TABLE agent_data_catalog ( data_domain VARCHAR(50) COMMENT 数据域如 product, order, data_entity VARCHAR(100) COMMENT 数据实体如 basic_info, manual, serving_type VARCHAR(20) COMMENT 服务类型如 structured_db, vector_search, api, endpoint_config JSON COMMENT 连接配置如 {jdbcUrl: ..., table: ...}, schema_description TEXT COMMENT 语义化描述供智能体理解, access_policy VARCHAR(100) COMMENT 访问策略标识 );插入示例数据INSERT INTO agent_data_catalog VALUES (product, basic_info, structured_db, {jdbcUrl: jdbc:mysql://adb-xxx:3306/serving_db, table: products_serving}, 存储产品核心信息包括ID、名称、类别和JSON格式的属性如颜色、尺寸。可用于回答产品型号、属性等问题。, policy_product_read), (product, usage_manual, vector_search, {es_endpoint: https://es-cn-xxx.elasticsearch.aliyuncs.com:9200, index: product_docs}, 存储产品说明书的文本片段及其向量。可用于回答“如何操作”、“故障排除”等深层次问题。, policy_product_read);智能体在需要数据时首先查询此目录根据问题意图决定访问哪个数据源。4. 开发 AI 智能体应用消费 Agentic Lake 数据现在数据已经“就绪”我们来开发一个 Spring Boot 智能体应用它能够理解用户问题从正确的数据源获取信息并组织成回答。4.1 应用架构与配置应用包含以下核心组件意图识别器判断用户问题属于哪个data_domain和data_entity。数据查询器根据意图从对应的数据源AnalyticDB MySQL 或 Elasticsearch查询数据。提示词工程将查询结果和用户问题组合成有效的提示词Prompt。大模型调用调用大模型如通义千问、GPT生成最终回答。application.yml配置spring: ai: openai: api-key: ${OPENAI_API_KEY} # 或使用阿里云灵积模型 base-url 和 api-key base-url: https://dashscope.aliyuncs.com/compatible-mode/v1 # 示例阿里云灵积兼容端点 chat: options: model: qwen-max # 指定模型 datasource: # 连接 Agentic Lake 的元数据目录 catalog: url: jdbc:mysql://meta-db.xxx.com:3306/agent_catalog username: ${CATALOG_DB_USER} password: ${CATALOG_DB_PWD} # 连接 AnalyticDB MySQL (产品结构化数据) product-db: url: jdbc:mysql://adb-xxx.xxx.com:3306/serving_db username: ${PRODUCT_DB_USER} password: ${PRODUCT_DB_PWD} elasticsearch: # 连接向量检索服务 uris: https://es-cn-xxx.elasticsearch.aliyuncs.com:9200 username: ${ES_USER} password: ${ES_PWD} # 自定义配置 agentic: >Service Slf4j public class DataRoutingService { Autowired private JdbcTemplate catalogJdbcTemplate; // 连接元数据目录的JdbcTemplate /** * 根据用户问题决定查询哪个数据源 * param userQuestion 用户问题 * return 数据源配置信息 */ public DataSourceConfig routeToDataSource(String userQuestion) { // 简化版通过关键词匹配。生产环境应使用更复杂的NLU模型。 String domain product; String entity; if (userQuestion.contains(颜色) || userQuestion.contains(型号) || userQuestion.contains(价格)) { entity basic_info; } else if (userQuestion.contains(怎么用) || userQuestion.contains(步骤) || userQuestion.contains(故障)) { entity usage_manual; } else { entity basic_info; // 默认 } String sql SELECT serving_type, endpoint_config FROM agentic.getDataCatalogTable() WHERE data_domain ? AND data_entity ?; return catalogJdbcTemplate.queryForObject(sql, (rs, rowNum) - new DataSourceConfig( rs.getString(serving_type), rs.getString(endpoint_config) // JSON字符串 ), domain, entity); } Data AllArgsConstructor public static class DataSourceConfig { private String servingType; // structured_db, vector_search private String endpointConfigJson; } }2. 结构化数据查询器Component public class StructuredDataQueryService { Qualifier(productDbJdbcTemplate) Autowired private JdbcTemplate productDbJdbcTemplate; public String queryProductBasicInfo(String question) { // 从问题中提取关键词这里简化为查询所有属性 String sql SELECT name, attributes FROM products_serving WHERE category LIKE %手机% ORDER BY update_time DESC LIMIT 5; ListMapString, Object results productDbJdbcTemplate.queryForList(sql); // 将结果格式化为自然语言描述便于后续拼接到Prompt中 StringBuilder context new StringBuilder(当前产品信息\n); for (MapString, Object row : results) { String name (String) row.get(name); String attrJson (String) row.get(attributes); // 解析JSON attributes context.append(String.format(- 产品%s 属性%s\n, name, attrJson)); } return context.toString(); } }3. 向量检索查询器Component public class VectorSearchService { Autowired private ElasticsearchRestTemplate elasticsearchRestTemplate; public String searchRelevantText(String question) { // 1. 先将用户问题转换为向量 (这里需要调用嵌入模型为简化假设已有方法) float[] questionVector getEmbedding(question); // 2. 在Elasticsearch中执行向量相似度搜索 NativeSearchQuery query new NativeSearchQueryBuilder() .withQuery(QueryBuilders.scriptScoreQuery( QueryBuilders.matchAllQuery(), new ScriptScoreQueryBuilder.Script( new Script(ScriptType.INLINE, painless, cosineSimilarity(params.query_vector, embedding) 1.0, Collections.singletonMap(query_vector, questionVector)) ))) .withPageable(PageRequest.of(0, 3)) // 取最相关的3条 .build(); SearchHitsDocumentChunk searchHits elasticsearchRestTemplate.search(query, DocumentChunk.class, IndexCoordinates.of(product_docs)); // 3. 组合检索结果 StringBuilder context new StringBuilder(相关产品文档片段\n); for (SearchHitDocumentChunk hit : searchHits) { context.append(- ).append(hit.getContent().getText()).append(\n); } return context.toString(); } private float[] getEmbedding(String text) { // 调用PAI-EAS或本地嵌入模型API返回向量 // 实现略 return new float[768]; } Document(indexName product_docs) Data public static class DocumentChunk { Id private String id; Field(type FieldType.Text) private String text; Field(type FieldType.Dense_Vector, dims 768) // 假设向量维度768 private float[] embedding; private String source; } }4. 智能体服务编排层Service public class CustomerServiceAgent { Autowired private DataRoutingService routingService; Autowired private StructuredDataQueryService structuredQueryService; Autowired private VectorSearchService vectorSearchService; Autowired private OpenAiChatClient chatClient; // Spring AI 的 ChatClient public String answerQuestion(String userQuestion) { // 1. 路由数据源 DataRoutingService.DataSourceConfig config routingService.routeToDataSource(userQuestion); // 2. 根据类型查询数据 String dataContext; if (structured_db.equals(config.getServingType())) { dataContext structuredQueryService.queryProductBasicInfo(userQuestion); } else if (vector_search.equals(config.getServingType())) { dataContext vectorSearchService.searchRelevantText(userQuestion); } else { dataContext 未找到相关数据。; } // 3. 构建Prompt注入查询到的数据上下文 String systemPrompt 你是一个专业的智能客服。请严格根据以下提供的数据信息来回答问题。 如果数据信息不足以回答问题请如实告知用户不要编造信息。 数据信息 %s .formatted(dataContext); UserMessage userMessage new UserMessage(userQuestion); SystemMessage systemMessage new SystemMessage(systemPrompt); // 4. 调用大模型生成回答 ChatResponse response chatClient.call(new Prompt(List.of(systemMessage, userMessage))); return response.getResult().getOutput().getContent(); } }4.3 运行与验证启动 Spring Boot 应用后通过一个简单的 REST 接口进行测试RestController RequestMapping(/api/agent) public class AgentController { Autowired private CustomerServiceAgent agent; PostMapping(/ask) public String ask(RequestBody MapString, String request) { String question request.get(question); return agent.answerQuestion(question); } }使用curl或 Postman 发送请求curl -X POST http://localhost:8080/api/agent/ask \ -H Content-Type: application/json \ -d {question:最新款的智能手机有哪些颜色}预期结果智能体会先通过DataRoutingService识别出这是关于产品基本信息的查询然后从 AnalyticDB MySQL 中获取最新的产品列表及其属性 JSON最后将格式化后的数据上下文与问题一起提交给大模型生成类似“根据当前信息最新款智能手机X提供曜石黑、冰川银、珊瑚粉三种颜色。”的回答。5. 常见问题排查与优化实践在构建和运行上述流程时你可能会遇到以下典型问题。5.1 数据链路问题排查问题现象可能原因检查点解决方案智能体回答“未找到数据”或数据过时。1. DataWorks/Flink 同步任务失败或延迟。2. 元数据目录agent_data_catalog配置错误。3. 数据源AnalyticDB/ES连接失败。1. 检查 DataWorks 任务实例日志。2. 检查 Flink 作业运行状态和 Checkpoint。3. 在智能体应用日志中查看DataRoutingService的输出和 SQL 查询是否报错。4. 直接连接目标数据库验证数据是否存在且最新。1. 修复同步任务检查网络、权限和资源。2. 核对endpoint_configJSON 中的连接串、表名/索引名。3. 检查 VPC、白名单、账号密码。向量搜索返回结果不相关。1. 文本分块策略不合理块太大或太小。2. 嵌入模型不适合领域数据。3. 向量索引类型或相似度算法不匹配。1. 检查分块后的文本是否语义完整。2. 在不同模型上测试同一批数据的检索效果。3. 检查 Elasticsearch 中索引的 mapping确认dense_vector维度和模型输出一致。1. 调整分块大小和重叠Overlap策略。2. 尝试领域微调过的嵌入模型或更换模型。3. 在创建索引时指定正确的相似度算法如cosine。大模型回答未基于提供的数据上下文产生“幻觉”。1. Prompt 设计不佳模型忽略了系统指令。2. 数据上下文过长或格式混乱模型无法有效提取信息。1. 打印出最终发送给模型的完整 Prompt检查系统指令是否清晰、数据上下文是否在正确位置。2. 简化数据上下文的格式使用更清晰的标记如产品名称 颜色值。1. 强化系统 Prompt使用“严格根据”、“必须引用”等指令。尝试 Few-shot Prompting提供正确回答的示例。2. 对查询结果进行二次加工和总结只提供最精炼的关键信息。5.2 性能与成本优化缓存数据上下文对于热点问题如热门产品信息智能体的数据查询结果可以缓存如使用 Redis避免每次请求都查询数据库和向量索引。注意设置合理的过期时间与底层数据更新频率对齐。异步与批处理向量生成步骤文本转向量通常是瓶颈。可以对 OSS 中的文档进行异步批处理而非实时处理。使用 DataWorks 或 Flink 作业在低峰期完成向量化。查询优化结构化查询为 AnalyticDB MySQL 中的高频查询字段建立索引。向量检索控制返回的向量数量Top K并使用高效的近似最近邻搜索ANN算法索引如 HNSW。模型调用优化大模型 API 调用是主要成本。可以考虑上下文压缩在将数据注入 Prompt 前先使用一个小模型或规则进行摘要和过滤。模型选型根据问题复杂度选择不同规格的模型简单查询使用轻量级模型。5.3 安全与权限最佳实践最小权限原则为 DataWorks 任务、Flink 作业、智能体应用分别创建独立的 RAM 子账号授予其完成本职工作所需的最小权限如只读某个 OSS Bucket、只写某个 ADB 表。数据脱敏在数据同步到服务层AnalyticDB MySQL前通过 DataWorks 的数据脱敏功能对手机号、邮箱等敏感字段进行掩码处理。确保智能体无法接触到原始敏感数据。审计日志确保所有数据访问包括 DataWorks 任务、智能体应用的查询都有完整的操作审计日志。阿里云 ActionTrail 可以记录云 API 调用应用自身也应记录关键的数据查询请求。Prompt 注入防护对用户输入进行基本的清洗和检查防止恶意用户通过精心构造的问题让模型执行非预期的数据查询或操作。6. 扩展方向与演进思考本文展示的只是一个最小化的 Agentic Lake 实现。在实际企业级场景中可以从以下几个方向深化自动化元数据管理使用数据地图如 DataWorks 的数据目录自动采集数据源的 Schema、血缘和业务标签并同步到agent_data_catalog减少手动维护。意图识别升级用一个小型微调模型或更复杂的规则/分类器替代简单的关键词匹配更精准地路由用户问题。多模态数据处理扩展架构以支持图像、音频等非结构化数据。例如将产品图片通过视觉模型生成描述和向量并存入库中支持“找类似这款外观的手机”这类查询。Agent 工作流编排复杂问题可能需要串联多个数据查询步骤。可以引入 LangChain、Spring AI 的 Agent 框架让智能体自主决定调用哪个工具查询结构化DB、搜索向量库、调用计算API并组合结果。评估与反馈闭环建立智能体回答质量的评估体系自动人工将错误案例反馈到数据层如补充缺失数据、优化元数据描述和模型层优化 Prompt形成持续改进闭环。构建 Agentic Lake 的本质是将数据团队的工作从“服务于报表和数据分析师”扩展到“服务于 AI 智能体”。这要求数据管道具备更高的实时性、更丰富的语义层和更标准化的服务接口。通过阿里云现有服务的组合我们已经可以搭建出这一架构的雏形。真正的挑战在于跨团队协作——数据工程师、算法工程师和应用开发者需要共同定义智能体所需的数据契约并持续维护这个动态的、以 AI 为中心的数据生态系统。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价