第八篇:Google ADK 企业级集成实战——打造智能知识库问答系统

在前几篇文章中,我们共同探索了 ADK 的核心理念、架构以及如何构建具备高级认知能力的 AI 代理。随着我们对 ADK 的理解日益深入,是时候将目光投向更宏大、更复杂的应用场景了——企业级应用集成

在当今数据驱动的商业环境中,AI 代理如果不能与企业现有的系统和数据源深度融合,其价值将大打折扣。本篇文章将带您深入探讨如何利用 ADK 构建能够连接企业数据孤岛、理解企业内部文档、并遵循企业安全规范的智能代理。我们将重点解析企业数据源连接文档检索与 RAG (检索增强生成) 架构并通过一个构建企业知识库问答系统的实例,展示 ADK 在企业集成中的强大威力。


🔗 连接企业数据源:打破信息壁垒

企业数据往往散落在各个独立的系统中:数据库、CRM、ERP、内部 API 等。要让 AI 代理真正赋能企业,首先必须打通这些数据连接。

挑战与机遇:

  • 数据孤岛:不同系统间数据格式各异,访问方式不一。
  • 实时性要求:许多业务场景需要代理访问最新的数据。
  • 安全性与合规性:企业数据访问必须严格遵守安全策略和合规要求。

ADK 的角色:

ADK 灵活的工具机制为连接企业数据源提供了坚实基础:

  1. FunctionTool:这是最直接的方式。开发者可以将访问特定数据库、调用内部 API 或处理特定数据格式的 Python 函数封装为 FunctionTool 。例如,一个 FunctionTool 可以实现查询 SQL 数据库、请求内部 REST API、或者解析特定的文件格式。
  1. APIHubToolset 与 OpenAPI:如果企业的 API 通过 Apigee API Hub 管理并遵循 OpenAPI 规范,APIHubToolset 可以自动生成 ADK 工具,极大简化集成工作 。
  1. MCPToolset (模型上下文协议):对于遵循 MCP 标准暴露其能力的企业服务,MCPToolset 能够实现“即插即用”式的集成,提供标准化的交互方式 。

集成策略:

  • 直接连接:在工具内部实现数据库连接、API 调用等逻辑。此时务必考虑连接池、超时处理和凭证安全。
  • API 网关:通过企业统一的 API 网关访问内部服务,有助于集中管理安全、监控和流控。
  • 数据虚拟化/中间层:构建一个中间服务层,封装对底层复杂数据源的访问,为 ADK 代理提供更简洁、统一的数据接口。

🧠 文档检索与 RAG 架构:赋予代理企业“记忆”

企业内部蕴藏着海量的知识,如政策文档、技术手册、项目报告、历史邮件等。让 AI 代理能够理解并利用这些知识,是提升其智能水平的关键。检索增强生成 (Retrieval Augmented Generation, RAG) 架构正是为此而生。

RAG 的核心思想:

RAG 结合了检索系统(从知识库中查找相关信息)和大型语言模型(LLM,利用检索到的信息生成回答)的优势。它能有效减少 LLM 的“幻觉”现象,确保回答基于事实,并能动态更新知识。

RAG 系统的核心组件:

  1. 知识库 (Knowledge Base):存储企业文档的地方。通常会对文档进行预处理(清洗、切块),然后使用嵌入模型 (Embedding Models) 将文本块转换为向量,存入向量数据库 (Vector Database)(如 Pinecone, FAISS, Vertex AI Vector Search)以便进行高效的相似性搜索。
  1. 检索器 (Retriever):接收用户查询,将其转换为向量,然后在向量数据库中搜索最相关的文档片段。
  1. 大型语言模型 (LLM - Generator):ADK 代理的核心,如 Gemini。它接收原始查询和检索器返回的相关文档片段,然后综合这些信息生成最终答案。

在 ADK 中实现 RAG:

我们可以通过 FunctionTool 在 ADK 中集成 RAG 的检索能力:

  • 创建 knowledge_retrieval_tool
  • 这个工具接收用户的查询字符串。
  • 内部逻辑负责:
  1. 使用与知识库一致的嵌入模型将查询文本转换为向量。
  2. 查询向量数据库,获取最相关的文档片段(chunks)。
  3. 返回这些文档片段作为工具的输出。
  • 配置 ADK 代理 (LlmAgent):
  1. knowledge_retrieval_tool 添加到代理的 tools 列表中 。
  2. 精心设计代理的 instruction (提示) 。这个提示至关重要,需要引导 LLM:
  3. 理解何时应该使用 knowledge_retrieval_tool(例如,当用户问题涉及内部知识时)。
  4. 如何利用工具返回的文档片段来回答问题。
  5. 强调回答必须严格基于检索到的信息,避免编造。
  6. 如果未找到相关信息,应如实告知用户。

🚀 实例:构建企业知识库问答系统

现在,我们将综合运用上述概念,勾勒出一个基于 ADK 的企业知识库问答系统的实现蓝图。

场景:一家公司希望构建一个 AI 助手,能够回答员工关于公司政策、IT 支持、产品信息等基于内部文档的问题。

高层架构

  1. 文档预处理与索引(离线)
  • 收集企业内部文档(PDF、Word、Confluence 页面等)。
  • 对文档进行清洗、分块 (chunking)。
  • 使用嵌入模型(如 Google 的 text-embedding-004)将文本块转换为向量。
  • 将向量及其对应的文本内容存储到向量数据库中(如 Vertex AI Vector Search)。
  1. ADK 问答代理(在线)
  • 用户通过前端界面与 ADK 代理交互。
  • 代理使用 RAG 模式:调用 knowledge_retrieval_tool 从向量数据库检索相关信息,然后由 LLM 生成答案。

源代码如下

__init__.py文件

from . import agent

.env文件

# 不同LLM提供商的API密钥

# 将此文件重命名为.env并根据需要添加你的密钥

# Google API密钥,用于Gemini模型

GOOGLE_GENAI_USE_VERTEXAI="False"

GOOGLE_API_KEY=**********

QWEN_API_KEY = "sk-f22763*******8d77c"

agent.py文件

import os
import sys
import importlib.util
from google.adk.agents import Agent, LlmAgent
from google.adk.tools import FunctionTool
from google.adk.models.lite_llm import LiteLlm
from typing import Dict, Any

# 定义动态导入函数
def import_module_from_path(module_name, file_path):
    """动态导入模块"""
    spec = importlib.util.spec_from_file_location(module_name, file_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

# 确定当前目录
current_dir = os.path.dirname(os.path.abspath(__file__))

try:
    # 尝试普通导入
    from knowledge_tool import knowledge_retrieval_tool, initialize_knowledge_base_with_examples
except ImportError:
    # 如果失败,尝试动态导入
    knowledge_tool_module = import_module_from_path(
        "knowledge_tool", os.path.join(current_dir, "knowledge_tool.py")
    )
    knowledge_retrieval_tool = knowledge_tool_module.knowledge_retrieval_tool
    initialize_knowledge_base_with_examples = knowledge_tool_module.initialize_knowledge_base_with_examples


# 将Python函数封装为ADK工具
knowledge_tool_instance = FunctionTool(knowledge_retrieval_tool)

# API密钥设置
DEFAULT_DASHSCOPE_API_KEY = "sk-f227634bb5614dd8b4eb29a95f38d77c"  # 请替换为您的实际密钥
DASHSCOPE_API_KEY = os.environ.get("DASHSCOPE_API_KEY", DEFAULT_DASHSCOPE_API_KEY)


# 企业知识库问答代理
enterprise_qna_agent = LlmAgent(
    name="EnterpriseKnowledgeAssistant",
    model=LiteLlm(
                model="openai/qwen-turbo",
                api_key=DASHSCOPE_API_KEY,
                api_base="https://dashscope.aliyuncs.com/compatible-mode/v1"
    ),
    tools=[knowledge_tool_instance],
    instruction="""
    你是一个企业内部知识问答助手。你的任务是根据用户的问题,利用 knowledge_retrieval_tool 从公司知识库中查找相关信息,并基于这些信息清晰、准确地回答用户。

    请遵循以下步骤:
    1. 分析用户的问题,理解其意图。
    2. 如果问题适合从知识库中查找答案,请立即调用 knowledge_retrieval_tool,并将用户的完整问题作为查询参数。
    3. 工具会返回相关的文档片段。仔细阅读这些片段。
    4. 严格根据检索到的文档片段内容来组织你的回答。不要添加外部知识或个人猜测。
    5. 如果检索到的文档片段包含答案,请清晰地呈现。你可以引用关键信息或总结要点。
    6. 如果工具返回 'status: "not_found"' 或检索到的文档与问题不相关,请明确告知用户你在公司知识库中没有找到直接答案,不要尝试编造。
    7. 保持回答专业、简洁、有帮助。

    示例:
    用户:"我们公司的年假政策是什么?"
    你的行动:[调用 knowledge_retrieval_tool(query="我们公司的年假政策是什么?")]
    (假设工具返回了相关政策片段)
    你的回答:[基于返回的片段进行回答,例如:"根据公司政策文档,员工每年享有XX天年假..."]

    用户:"如何配置新的开发环境?"
    你的行动:[调用 knowledge_retrieval_tool(query="如何配置新的开发环境?")]
    (假设工具返回了相关设置指南)
    你的回答:[基于返回的片段进行回答,例如:"配置新的开发环境,请参照以下步骤..."]
    """,
    output_key="qna_response"
)


# 为兼容 ADK 的要求,将智能体公开为 root_agent
root_agent = enterprise_qna_agent


# 在导入模块时初始化知识库
try:
    initialize_knowledge_base_with_examples()
except Exception as e:
    print(f"初始化知识库时出错: {e}")
    print("请确保已安装必要的依赖: pip install pymilvus 'pymilvus[model]'")

embedding.py文件

from typing import List, Union
import os
import sys
import numpy as np

# 设置本地模型路径
LOCAL_MODEL_PATH = r"D:\module\BAAI-bge-large-zh-v1.5"


class EmbeddingModel:
    """Text embedding model using local BGE model or fallback to random embeddings."""
    
    def __init__(self, model_path: str = LOCAL_MODEL_PATH):
        """
        Initialize the embedding model.
        
        Args:
            model_path: Path to the local embedding model
        """
        self.model_path = model_path
        self.dim = 1024  # BGE-large 模型的向量维度
        self._model_loaded = False
        self.model = None
        self.tokenizer = None
        
        # 尝试加载模型
        try:
            # 加载必要的库
            from transformers import AutoModel, AutoTokenizer
            import torch
            
            print(f"尝试从本地路径加载模型: {model_path}")
            # 加载模型和分词器
            self.tokenizer = AutoTokenizer.from_pretrained(model_path)
            self.model = AutoModel.from_pretrained(model_path)
            
            # 如果有GPU,将模型移至GPU
            self.device = 'cuda' if torch.cuda.is_available() else 'cpu'
            self.model.to(self.device)
            self.model.eval()  # 设置为评估模式
            
            self._model_loaded = True
            print(f"成功加载模型: {model_path}")
            
        except Exception as e:
            print(f"警告: 无法加载嵌入模型: {str(e)}")
            print("将使用随机向量作为演示用途。")
            self._model_loaded = False
    
    def _get_embeddings(self, text_batch):
        """使用BGE模型获取文本的嵌入向量"""
        import torch
        
        # 对文本进行编码
        encoded_input = self.tokenizer(
            text_batch, 
            padding=True, 
            truncation=True, 
            max_length=512, 
            return_tensors='pt'
        ).to(self.device)
        
        # 推理
        with torch.no_grad():
            outputs = self.model(**encoded_input)
            # 使用最后一层的隐藏状态的平均值作为嵌入
            embeddings = self._mean_pooling(outputs.last_hidden_state, encoded_input['attention_mask'])
            # 标准化
            embeddings = torch.nn.functional.normalize(embeddings, p=2, dim=1)
        
        return embeddings.cpu().numpy()
    
    def _mean_pooling(self, token_embeddings, attention_mask):
        """对token嵌入进行平均池化"""
        import torch
        
        input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
        return torch.sum(token_embeddings * input_mask_expanded, 1) / torch.clamp(input_mask_expanded.sum(1), min=1e-9)
    
    def embed(self, text: Union[str, List[str]]) -> List[List[float]]:
        """
        Convert text to vector embeddings.
        
        Args:
            text: Single string or list of strings to embed
        
        Returns:
            List of vector embeddings
        """
        # 确保输入格式一致,单个字符串转为列表
        if isinstance(text, str):
            texts = [text]
        else:
            texts = text
        
        # 如果模型加载失败,返回随机向量
        if not self._model_loaded:
            import random
            return [[random.uniform(-1, 1) for _ in range(self.dim)] for _ in texts]
        
        # 使用模型生成嵌入
        try:
            embeddings = self._get_embeddings(texts)
            return embeddings.tolist()
        except Exception as e:
            print(f"生成嵌入时出错: {str(e)}")
            print("返回随机向量作为后备方案")
            import random
            return [[random.uniform(-1, 1) for _ in range(self.dim)] for _ in texts] 

knowledge_tool.py

from typing import Dict, Any, List, Optional
import os
import sys
import importlib.util

# 定义动态导入函数
def import_module_from_path(module_name, file_path):
    """动态导入模块"""
    spec = importlib.util.spec_from_file_location(module_name, file_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

# 确定当前目录
current_dir = os.path.dirname(os.path.abspath(__file__))

# 尝试导入简单向量数据库
try:
    from simple_vector_db import SimpleVectorDB, get_vector_db
except ImportError:
    # 如果失败,尝试动态导入
    vector_db_module = import_module_from_path(
        "simple_vector_db", os.path.join(current_dir, "simple_vector_db.py")
    )
    SimpleVectorDB = vector_db_module.SimpleVectorDB
    get_vector_db = vector_db_module.get_vector_db

# 导入嵌入模型
try:
    from embedding import EmbeddingModel
except ImportError:
    # 如果失败,尝试动态导入
    embedding_module = import_module_from_path(
        "embedding", os.path.join(current_dir, "embedding.py")
    )
    EmbeddingModel = embedding_module.EmbeddingModel


# Initialize the vector database and embedding model as module-level singletons
# This ensures we only create one instance even if the tool is called multiple times
_vector_db = None
_embedding_model = None


def get_embedding_model() -> EmbeddingModel:
    """Get or create the embedding model singleton."""
    global _embedding_model
    if _embedding_model is None:
        _embedding_model = EmbeddingModel()
    return _embedding_model


def knowledge_retrieval_tool(query: str, tool_context=None) -> Dict[str, Any]:
    """
    从企业知识库中检索与用户查询相关的文档片段。

    Args:
        query: 用户提出的问题或查询。
        tool_context: ADK 工具上下文,可用于访问会话状态或认证信息。

    Returns:
        一个包含检索到的文档片段列表的字典,
        例如: {"status": "success", "documents": ["文档片段1...", "文档片段2..."]}
             {"status": "not_found", "message": "未找到相关文档。"}
    """
    print(f"--- 工具:knowledge_retrieval_tool 被调用,查询={query} ---")
    
    try:
        # 获取向量数据库和嵌入模型实例
        vector_db = get_vector_db()
        embedding_model = get_embedding_model()
        
        # 将用户查询转换为向量表示
        query_embedding = embedding_model.embed(query)
        
        # 在向量数据库中搜索相似文档
        search_results = vector_db.search(
            query_vectors=query_embedding,
            limit=3  # 返回前3个最相关的结果
        )
        
        # 检查是否有结果
        if not search_results:
            return {
                "status": "not_found",
                "message": "在企业知识库中未找到与您查询直接相关的文档。"
            }
        
        # 提取文档文本并返回
        documents = [result["text"] for result in search_results]
        
        return {
            "status": "success",
            "documents": documents
        }
        
    except Exception as e:
        print(f"知识检索工具出错: {e}")
        return {
            "status": "error",
            "error_message": f"检索文档时发生错误: {str(e)}"
        }


def initialize_knowledge_base_with_examples() -> None:
    """用示例数据初始化知识库,仅用于演示目的。"""
    vector_db = get_vector_db()
    embedding_model = get_embedding_model()
    
    # 示例文档
    documents = [
        {
            "text": "HR政策文档摘录1:公司年假政策规定每位员工每年可享有20天带薪假期。新员工需要工作满3个月后方可申请休假。休假申请需提前至少一周提交给直属经理审批。",
            "metadata": {"source": "HR政策手册", "category": "假期政策", "updated": "2023-09-01"}
        },
        {
            "text": "HR政策文档摘录2:病假规定超过3天需要提供医生证明。病假期间,员工薪资将按照公司规定的比例发放。紧急情况下,请通过电话或短信及时通知您的直属经理。",
            "metadata": {"source": "HR政策手册", "category": "假期政策", "updated": "2023-09-01"}
        },
        {
            "text": "技术设置指南摘录1:配置公司VPN,请按照以下步骤操作:1.从内部门户下载VPN客户端 2.使用您的公司邮箱和密码登录 3.选择最近的服务器位置 4.连接后,您将可以访问内部资源。",
            "metadata": {"source": "IT设置指南", "category": "网络配置", "updated": "2023-10-15"}
        },
        {
            "text": "技术设置指南摘录2:安装新软件前,请确保您的操作系统已更新到最新版本。所有软件安装必须通过公司软件中心进行,不得自行下载安装未经批准的软件。",
            "metadata": {"source": "IT设置指南", "category": "软件安装", "updated": "2023-10-15"}
        },
        {
            "text": "新员工入职指南:您的第一天将安排参观办公室,了解公司文化,并与您的团队成员见面。请携带您的身份证件和银行账户信息,以便HR部门完成入职手续。",
            "metadata": {"source": "入职手册", "category": "新员工", "updated": "2023-08-10"}
        },
        {
            "text": "远程工作政策:公司允许员工每周远程工作不超过2天。远程工作期间,员工需要保持在线状态并参加所有必要的会议。每周必须在办公室工作至少3天。",
            "metadata": {"source": "工作场所政策", "category": "工作安排", "updated": "2023-11-05"}
        }
    ]
    
    # 为每个文档生成向量嵌入
    document_texts = [doc["text"] for doc in documents]
    embeddings = embedding_model.embed(document_texts)
    
    # 准备要插入的数据
    data_to_insert = []
    for i, (doc, embedding) in enumerate(zip(documents, embeddings)):
        data_to_insert.append({
            "id": i,
            "vector": embedding,
            "text": doc["text"],
            "metadata": doc["metadata"]
        })
    
    # 删除现有集合并创建新的
    vector_db.drop_collection()
    # 插入文档
    vector_db.add_documents(data_to_insert)
    
    print(f"成功初始化知识库,添加了 {len(data_to_insert)} 个文档。") 

simple_vector_db.py

"""
基于内存的简单向量数据库

这个模块提供了一个简单的基于内存的向量数据库实现,用于替代Milvus Lite
主要用于测试和演示,不需要额外的依赖
"""
import os
import numpy as np
from typing import List, Dict, Any, Optional


class SimpleVectorDB:
    """基于内存的简单向量数据库,用于存储和检索文档"""
    
    def __init__(self, collection_name: str = "documents", vector_dim: int = 1024):
        """
        初始化简单向量数据库
        
        Args:
            collection_name: 集合名称
            vector_dim: 向量维度
        """
        self.collection_name = collection_name
        self.vector_dim = vector_dim
        self.documents = []  # 存储文档和向量
        self.next_id = 0  # 用于生成唯一ID
    
    def add_documents(self, documents: List[Dict[str, Any]]) -> List[int]:
        """
        添加文档到向量数据库
        
        Args:
            documents: 文档列表,每个文档包含'id', 'vector', 'text'和'metadata'
        
        Returns:
            添加的文档ID列表
        """
        added_ids = []
        
        for doc in documents:
            # 使用提供的ID或生成新ID
            doc_id = doc.get('id', self.next_id)
            self.next_id = max(self.next_id, doc_id + 1)
            
            # 添加文档
            self.documents.append({
                'id': doc_id,
                'vector': np.array(doc['vector']),  # 转换为numpy数组以便计算
                'text': doc['text'],
                'metadata': doc.get('metadata', {})
            })
            
            added_ids.append(doc_id)
        
        print(f"添加了{len(documents)}个文档到向量数据库")
        return added_ids
    
    def search(self, query_vectors: List[List[float]], limit: int = 3, 
               filter_expr: Optional[str] = None) -> List[Dict[str, Any]]:
        """
        在向量数据库中搜索相似文档
        
        Args:
            query_vectors: 查询向量列表
            limit: 返回结果的最大数量
            filter_expr: 过滤表达式(此简单实现暂不支持复杂过滤)
        
        Returns:
            搜索结果列表
        """
        if not self.documents:
            print("警告: 向量数据库为空")
            return []
        
        # 我们只处理第一个查询向量
        query_vector = np.array(query_vectors[0])
        
        # 计算余弦相似度
        results = []
        for doc in self.documents:
            # 计算余弦相似度
            similarity = self._cosine_similarity(query_vector, doc['vector'])
            
            # 如果有过滤表达式,这里应该进行过滤
            # 目前仅支持简单的元数据字段匹配
            if filter_expr and not self._simple_filter(doc['metadata'], filter_expr):
                continue
                
            results.append({
                'id': doc['id'],
                'distance': 1 - similarity,  # 转换相似度为距离
                'text': doc['text'],
                'metadata': doc['metadata']
            })
        
        # 按相似度排序(距离越小越相似)
        results.sort(key=lambda x: x['distance'])
        
        # 限制结果数量
        return results[:limit]
    
    def _cosine_similarity(self, vec1: np.ndarray, vec2: np.ndarray) -> float:
        """计算两个向量的余弦相似度"""
        dot_product = np.dot(vec1, vec2)
        norm_a = np.linalg.norm(vec1)
        norm_b = np.linalg.norm(vec2)
        
        # 避免除以零
        if norm_a == 0 or norm_b == 0:
            return 0
            
        return dot_product / (norm_a * norm_b)
    
    def _simple_filter(self, metadata: Dict[str, Any], filter_expr: str) -> bool:
        """
        简单的元数据过滤器
        
        Args:
            metadata: 文档元数据
            filter_expr: 简单的过滤表达式,格式为"field=value"
        
        Returns:
            是否通过过滤器
        """
        try:
            if '=' not in filter_expr:
                return True
                
            field, value = filter_expr.split('=', 1)
            field = field.strip()
            value = value.strip().strip('"\'')  # 移除可能的引号
            
            # 检查元数据字段是否匹配
            return str(metadata.get(field)) == value
        except:
            # 过滤表达式错误,默认通过
            return True
    
    def delete_documents(self, ids: List[int] = None) -> List[int]:
        """
        从向量数据库中删除文档
        
        Args:
            ids: 要删除的文档ID列表
        
        Returns:
            已删除的文档ID列表
        """
        if not ids:
            return []
            
        deleted_ids = []
        remaining_docs = []
        
        for doc in self.documents:
            if doc['id'] in ids:
                deleted_ids.append(doc['id'])
            else:
                remaining_docs.append(doc)
        
        self.documents = remaining_docs
        return deleted_ids
    
    def drop_collection(self) -> None:
        """删除整个集合"""
        self.documents = []
        print(f"集合 {self.collection_name} 已清空")


# 全局实例,用于替代Milvus客户端
_simple_vector_db = None


def get_vector_db(db_path: str = None, collection_name: str = "documents", vector_dim: int = 1024):
    """获取向量数据库单例"""
    global _simple_vector_db
    if _simple_vector_db is None:
        _simple_vector_db = SimpleVectorDB(collection_name, vector_dim)
    return _simple_vector_db 

工作流程:

  1. 员工向问答系统提问(例如:“公司的报销流程是怎样的?”)。
  1. ADK enterprise_qna_agent 接收到问题。
  1. 根据其 instruction,LLM 决定调用 knowledge_retrieval_tool,并将问题作为查询参数。
  1. knowledge_retrieval_tool 将查询转换为向量,在企业向量数据库中搜索相关文档块,并(如果需要)根据用户权限过滤结果。
  1. 检索到的文档块作为上下文返回给 enterprise_qna_agent 的 LLM。
  1. LLM 结合原始问题和检索到的上下文,生成一个基于企业知识的回答,并通过前端界面展示给员工。

需要注意的内容:

1、向量模型采用的是放在本地的 D:\module\BAAI-bge-large-zh-v1.5 模型

2、向量库暂时采用的是内存存储

运行展示如下:输入知识库中的问答则可以调用知识库工具


总结与展望

通过将 ADK 与企业数据源、RAG 架构以及健全的安全机制相结合,我们可以构建出真正能够解决企业实际问题、提升运营效率的智能代理。从连接已有的数据库和 API,到赋予代理理解海量内部文档的能力,再到确保每一次交互都安全合规,ADK 提供了灵活而强大的工具集来应对这些挑战。

我们今天构建的企业知识库问答系统仅仅是一个开始。想象一下,这样的代理还可以扩展到自动化复杂业务流程、提供个性化客户支持、辅助进行数据分析与决策等更多高级场景。

在下一篇文章中,我们将继续探索 ADK 的更多高级特性与应用场景。敬请期待!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值