1. 项目概述与核心价值

最近在折腾一个挺有意思的小项目,叫 lyw123www/chatgpt-to-kelivo 。乍一看这个仓库名,可能有点摸不着头脑,但如果你同时是ChatGPT这类AI对话工具的重度用户,又恰好对知识库或信息整理有刚需,那这个项目很可能就是你一直在找的“桥梁”。简单来说,它解决了一个非常具体且高频的痛点: 如何将你在ChatGPT(或其他兼容OpenAI API的AI助手)中产生的、有价值的对话内容,自动、结构化地同步到你自己的知识库系统中 。这里的“kelivo”我理解为一个知识库或笔记系统的代称(可能是自建系统,也可能是类似Obsidian、Logseq等工具形成的本地知识网络)。

想象一下这个场景:你在和ChatGPT深入探讨一个技术问题,它给出了非常精彩的步骤解析、代码示例和原理说明。这段对话本身就是一个高质量的学习笔记或技术文档草稿。但问题来了,ChatGPT的对话历史是线性的、封闭的,很难被有效地分类、检索和长期复用。你不得不手动复制粘贴,再费劲地整理格式,这个过程极其低效,且容易遗漏。 chatgpt-to-kelivo 项目的核心目标,就是自动化这个“价值萃取”与“归档”的流程,让AI对话的产出能无缝流入你的个人或团队知识体系,真正成为可沉淀、可连接的资产。

这个项目适合所有希望构建“第二大脑”或系统化知识管理体系的从业者,无论是程序员、研究者、写作者还是学生。它不仅仅是一个简单的导出工具,更涉及对非结构化对话数据的解析、内容的重组标记(如添加标签、分类)、以及与目标知识库系统的API集成。接下来,我将深入拆解这个项目的设计思路、技术实现细节,并分享在搭建类似系统时可能遇到的“坑”和实战技巧。

2. 项目整体设计与架构思路

2.1 核心需求与方案选型

这个项目的需求非常明确: 监听或获取指定AI对话,解析其内容,并按照预定格式推送到指定的知识库 。但实现路径有多种,选择哪种取决于你的使用场景和技术栈。

2.1.1 数据获取方式的选择

这是第一个关键决策点。如何拿到ChatGPT的对话数据?

  1. 浏览器插件方案 :开发一个Chrome/Firefox插件,注入到ChatGPT Web界面中。插件可以监听DOM变化,捕获用户与AI的每一轮问答。这种方式 直接、实时 ,能获取最原始的对话数据,包括可能的富文本格式(如代码块、加粗)。但缺点是对接特定网站,如果ChatGPT的页面结构更新,插件可能需要适配。此外,需要用户安装插件,有一定使用门槛。
  2. OpenAI API 日志方案 :如果你直接使用OpenAI的API进行对话(例如通过命令行工具、自定义客户端或第三方应用),那么你可以直接收集API的请求和响应日志。这种方式 稳定、结构化程度高 ,因为你拿到的是纯净的JSON数据。但前提是你必须通过API调用,而不是使用Web界面。
  3. 导出文件解析方案 :ChatGPT官方或一些第三方工具支持导出对话历史为JSON、TXT或PDF。项目可以设计为一个后处理工具,定期或手动处理这些导出文件。这种方式 最通用、侵入性最低 ,但实时性差,且依赖导出功能的稳定性。

对于 lyw123www/chatgpt-to-kelivo 这类项目,我推测其更可能采用 方案1(浏览器插件) 方案2(API日志中间件) ,以实现较高的自动化程度。方案3通常作为补充或备选。

2.1.2 内容解析与结构化

获取到原始对话数据(可能是一段包含多轮Q&A的文本或JSON)后,下一步是解析和结构化。这不仅仅是简单的文本分割,而是需要理解对话的语义结构。

  • 对话分割 :将连续的对话流,按照“用户提问”和“AI回复”的轮次进行切分。这里要注意,一轮对话可能包含用户多次追问或AI分多条消息回复的情况,需要合理合并。
  • 内容提取与增强
    • 元数据提取 :自动从对话中提取可能的关键词作为标签(Tag)。这可以通过简单的关键词匹配,或集成一个轻量级的NLP模型(如TF-IDF、TextRank算法)来实现。
    • 代码块识别与高亮 :如果对话中包含代码,需要识别其语言类型(如Python, JavaScript),并在推送到知识库时保留正确的代码块语法,以便目标知识库能正确渲染。
    • 总结生成 :可以为每一段较长的AI回复,自动生成一个简短的摘要,作为知识库条目的描述或预览。

2.1.3 目标知识库(Kelivo)的对接

“Kelivo”在这里是一个抽象概念。在实际实现中,它可以是:

  • 本地文件系统 :将解析后的内容生成为Markdown文件,保存到指定目录。这可以与Obsidian、Logseq、Typora等本地优先的笔记工具完美配合。这是 最简单、最可靠的方案 ,兼容性极强。
  • 云笔记API :如Notion、语雀、飞书文档的API。需要处理OAuth认证、页面创建、内容块(Block)组装等复杂逻辑。功能强大,但依赖第三方服务稳定性。
  • 自建知识库系统 :通过其提供的RESTful API或GraphQL接口进行推送。这提供了最大的灵活性。

项目架构上,通常会采用 “数据采集 -> 数据处理 -> 数据推送” 的管道(Pipeline)模式。每个环节解耦,方便独立扩展和替换。例如,数据采集模块可以同时支持插件和API日志两种方式;数据处理模块可以配置不同的解析规则;数据推送模块可以适配多个不同的知识库后端。

2.2 技术栈与工具选型解析

基于上述架构,一个典型的技术栈可能如下:

  • 核心语言 Python JavaScript/TypeScript
    • Python 优势在于数据处理和AI集成生态丰富(如用OpenAI自己的API来总结内容),适合做后端服务或CLI工具。
    • JavaScript/TypeScript 优势在于开发浏览器插件天然契合,且利用Node.js可以轻松构建全栈应用。对于 chatgpt-to-kelivo ,如果侧重浏览器插件,JS/TS是更自然的选择。
  • 浏览器插件开发 :使用Chrome Extensions Manifest V3规范进行开发。需要掌握 content_script (注入页面脚本)、 background service worker (后台处理)和 popup (插件图标交互)的基本用法。关键点是监听ChatGPT对话容器的DOM变化( MutationObserver )。
  • 数据处理
    • 文本处理 :使用 langchain TextSplitter 进行智能文本分割,或者用 markdown-it 等库解析Markdown格式。
    • 关键词提取 :可以集成 jieba (中文)、 nltk spacy (英文)进行分词和关键词提取。为了轻量,也可以直接用正则表达式匹配高频技术术语。
  • 知识库推送
    • 本地文件 :使用Node.js的 fs 模块或Python的 os / pathlib 库即可。
    • Notion API :使用官方 @notionhq/client SDK。难点在于将对话内容映射为Notion的Block对象(段落、标题、代码块、引用等)。
    • Webhook或自定义API :使用 axios (JS)或 requests (Python)库发送HTTP请求。
  • 配置与持久化 :使用 JSON YAML 文件存储用户配置(如知识库类型、API密钥、保存路径、标签规则等)。敏感信息(如API Key)应考虑使用环境变量或安全的配置管理方式。
  • 任务调度 :如果需要定时运行,可以集成 node-cron (JS)或 schedule / APScheduler (Python)。

注意 :工具选型的核心原则是“够用就好,保持轻量”。这个项目的价值在于流程自动化,而不是堆砌复杂技术。初期应优先实现核心链路,再逐步优化体验和增加高级功能。

3. 核心模块实现与实操要点

3.1 数据采集模块的实战细节

我们以 浏览器插件方案 为例,深入讲解如何可靠地捕获ChatGPT的对话。

3.1.1 定位与监听对话元素

ChatGPT Web界面的DOM结构可能会变,但基本模式稳定:对话通常存在于一个具有特定类名或属性的容器内(例如,一个 div ,其类名可能包含 text-base group 等)。你需要使用开发者工具仔细分析。

  1. 打开ChatGPT网页,进入一次对话
  2. 右键检查 ,使用元素选择器工具,点击用户消息和AI回复消息,找到它们所在的公共父容器以及各自的消息单元。通常,每一轮对话(无论是用户还是AI)都包裹在一个具有角色标识的 div 中。
  3. 编写 content_script :这个脚本将注入到ChatGPT页面中。
    // content-script.js
    // 目标对话容器的选择器(示例,需根据实际情况调整)
    const CONVERSATION_SELECTOR = 'div[data-testid^="conversation-turn-"]';
    // 或者更稳定的方式:找到包含所有消息滚动区域的父元素
    const MAIN_CONTAINER = 'div.h-32.md\\:h-48.flex-shrink-0'; // 举例,需更新
    
    let lastMessageCount = 0;
    
    function extractConversation() {
      // 这里实现具体的对话提取逻辑
      const messageElements = document.querySelectorAll(CONVERSATION_SELECTOR);
      if (messageElements.length <= lastMessageCount) {
        return; // 没有新消息
      }
      const newMessages = Array.from(messageElements).slice(lastMessageCount);
      // 解析每个messageElement,区分用户和AI,提取文本和代码块
      const parsedMessages = newMessages.map(el => parseMessageElement(el));
      lastMessageCount = messageElements.length;
      
      // 将解析后的消息发送给background script处理
      chrome.runtime.sendMessage({
        type: 'NEW_MESSAGES',
        data: parsedMessages
      });
    }
    
    function parseMessageElement(el) {
      // 1. 判断角色:通过元素内的特定文本或图标判断是用户还是AI
      const isUser = el.querySelector('img[alt*="User"]') || el.innerText.includes('You');
      // 2. 提取纯文本和代码
      const textContent = el.innerText;
      const codeBlocks = Array.from(el.querySelectorAll('pre code')).map(code => ({
        language: code.className.replace('language-', '') || 'text',
        content: code.innerText
      }));
      return {
        role: isUser ? 'user' : 'assistant',
        text: textContent,
        codeBlocks: codeBlocks,
        timestamp: new Date().toISOString()
      };
    }
    
    // 使用MutationObserver监听容器内子节点的变化
    const observer = new MutationObserver((mutations) => {
      // 当观察到变化时,尝试提取对话
      extractConversation();
    });
    
    // 启动监听
    const targetNode = document.querySelector(MAIN_CONTAINER) || document.body;
    observer.observe(targetNode, { childList: true, subtree: true });
    

3.1.2 处理动态加载与分页

ChatGPT在滚动时会动态加载历史消息。我们的监听器需要能处理这种情况。上述的 MutationObserver 已经可以捕获DOM节点的添加。但更完善的做法是,在插件首次加载或页面刷新时,主动扫描并提取当前已加载的所有历史消息,建立一个初始快照,然后再监听新增。

3.1.3 与后台脚本通信

content_script 运行在页面上下文中,能力受限(例如不能直接访问 chrome.storage 的同步存储,或发起跨域请求到你的知识库API)。因此,它通常只负责采集数据,然后通过 chrome.runtime.sendMessage 将数据发送给插件的 background service worker

background.js 负责核心业务逻辑:接收消息、处理数据(去重、格式化)、调用知识库推送接口、管理状态和配置。

// background.js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === 'NEW_MESSAGES') {
    const messages = request.data;
    // 1. 去重:比较时间戳或内容哈希,避免重复处理同一消息
    // 2. 格式化:将消息数组组织成更结构化的对话单元
    const formattedConversation = formatConversation(messages);
    // 3. 调用处理函数
    processAndSaveConversation(formattedConversation);
  }
});

3.2 数据处理与增强模块

拿到结构化的消息数组后,我们需要将其转化为适合知识库存储的格式。

3.2.1 对话重组与格式化

一个典型的对话可能包含多轮交互。我们可能希望将一次完整的“提问-解答-追问-再解答”保存为一个知识条目。

function formatConversation(messages) {
  const sessions = [];
  let currentSession = { title: '', qaPairs: [] };
  let currentQuestion = null;

  for (const msg of messages) {
    if (msg.role === 'user') {
      // 如果是用户消息,且当前没有悬空的问题,则作为新问题的开始
      if (currentQuestion) {
        // 如果已有问题但AI还没回答,可能是不完整的对话,暂时忽略或特殊处理
      }
      currentQuestion = { question: msg.text, answer: '' };
    } else if (msg.role === 'assistant' && currentQuestion) {
      // 如果是AI消息,且当前有问题,则作为回答
      currentQuestion.answer = msg.text;
      // 这里可以合并代码块
      currentQuestion.codeBlocks = msg.codeBlocks;
      currentSession.qaPairs.push(currentQuestion);
      currentQuestion = null; // 重置,等待下一个问题
    }
  }
  // 为本次会话生成一个标题(例如,用第一个问题的前N个字符)
  if (currentSession.qaPairs.length > 0) {
    currentSession.title = generateTitle(currentSession.qaPairs[0].question);
    sessions.push(currentSession);
  }
  return sessions;
}

3.2.2 自动打标与分类

这是提升知识库可用性的关键。我们可以基于对话内容自动生成标签。

  • 基于规则的关键词匹配 :维护一个技术关键词词典(如“Python”、“Docker”、“机器学习”)。遍历对话文本,匹配到的关键词即可作为标签。简单有效,但不够智能。
  • 基于摘要模型 :调用一个轻量级的文本摘要或关键词提取API(例如,使用 TF-IDF 算法本地计算)。虽然 chatgpt-to-kelivo 项目本身可能不集成大模型,但这是一个很自然的增强方向——用AI来整理AI的对话。
    # 一个简单的Python示例,使用sklearn的TF-IDF
    from sklearn.feature_extraction.text import TfidfVectorizer
    import jieba # 用于中文分词
    
    def extract_keywords_zh(text, top_k=5):
        # 先分词
        words = jieba.lcut(text)
        corpus = [' '.join(words)] # 需要将分词结果用空格连接
        vectorizer = TfidfVectorizer()
        tfidf_matrix = vectorizer.fit_transform(corpus)
        feature_names = vectorizer.get_feature_names_out()
        # 获取第一个文档(即当前文本)的TF-IDF权重并排序
        sorted_items = sorted(zip(feature_names, tfidf_matrix.toarray()[0]), key=lambda x: x[1], reverse=True)
        keywords = [item[0] for item in sorted_items[:top_k]]
        return keywords
    
    对于英文,可以使用 nltk 库进行分词和停用词过滤。

3.2.3 生成Markdown内容

最终推送前,需要将结构化的会话数据转换为目标知识库支持的格式。Markdown是通用性最强的选择。

function convertSessionToMarkdown(session) {
  let md = `# ${session.title}\n\n`;
  md += `*自动同步自ChatGPT对话,时间:${new Date().toLocaleString()}*\n\n`;
  md += `**标签:** ${session.tags.join(', ')}\n\n---\n\n`;

  for (const [index, qa] of session.qaPairs.entries()) {
    md += `## Q${index + 1}: ${qa.question.substring(0, 50)}...\n\n`;
    md += `**用户提问:**\n${qa.question}\n\n`;
    md += `**AI回复:**\n${qa.answer}\n\n`;
    if (qa.codeBlocks && qa.codeBlocks.length > 0) {
      md += `**包含代码:**\n`;
      qa.codeBlocks.forEach(block => {
        md += `\`\`\`${block.language}\n${block.content}\n\`\`\`\n\n`;
      });
    }
    md += `---\n\n`;
  }
  return md;
}

3.3 知识库推送模块的实现

我们以 保存为本地Markdown文件 推送到Notion 两种最典型的场景为例。

3.3.1 保存至本地文件系统

这是最直接的方式。你需要决定文件如何组织。

  • 按日期归档 ./knowledge/2024-05/2024-05-20-ChatGPT-关于Docker网络配置的讨论.md
  • 按标签/分类归档 ./knowledge/Python/2024-05-20-解释装饰器.md
  • 使用唯一ID ./knowledge/ 目录下直接用 conversation_<timestamp>.md 命名。

在background script中,你需要获得写入本地文件的权限(Chrome插件需要 "downloads" 权限,但更常见的做法是让用户选择一个根目录,然后插件通过 chrome.fileSystem API 进行读写)。一个更简单的架构是:插件将数据发送给一个本地运行的 本地服务 (例如用Python Flask或Node.js Express写的一个小服务),由这个服务负责文件写入。这样避免了插件复杂的文件权限问题。

3.3.2 同步至Notion数据库

这需要更复杂的集成。

  1. 在Notion中创建集成(Integration) :访问Notion开发者页面,创建一个新的“内部集成”,获取 API Key
  2. 分享数据库给集成 :在Notion中创建一个数据库(Database),并邀请你刚创建的集成作为连接用户。
  3. 使用Notion API创建页面 :每个ChatGPT对话可以保存为数据库中的一个新页面(Page)。
    // 使用 @notionhq/client
    import { Client } from "@notionhq/client";
    const notion = new Client({ auth: process.env.NOTION_API_KEY });
    
    async function createNotionPage(session, databaseId) {
      const response = await notion.pages.create({
        parent: { database_id: databaseId },
        properties: {
          // 映射到数据库的属性
          'Title': { title: [{ text: { content: session.title } }] },
          'Tags': { multi_select: session.tags.map(tag => ({ name: tag })) },
          'Date': { date: { start: new Date().toISOString().split('T')[0] } }
        },
        children: session.qaPairs.flatMap(qa => [
          {
            object: 'block',
            type: 'heading_2',
            heading_2: { rich_text: [{ type: 'text', text: { content: `Q: ${qa.question.substring(0, 50)}...` } }] }
          },
          {
            object: 'block',
            type: 'paragraph',
            paragraph: { rich_text: [{ type: 'text', text: { content: `**用户提问:** ${qa.question}` } }] }
          },
          {
            object: 'block',
            type: 'paragraph',
            paragraph: { rich_text: [{ type: 'text', text: { content: `**AI回复:** ${qa.answer}` } }] }
          },
          // ... 处理代码块,类型为'code'
        ])
      });
      return response;
    }
    
    Notion API对Block的创建有速率限制,对于长对话需要分批次或做延迟处理。

3.3.3 配置化管理

用户需要能够灵活配置。可以在插件的 popup.html 页面中提供设置界面。

  • 存储方式 :本地路径、Notion数据库ID等。
  • 同步规则 :是实时同步每一条新消息,还是手动触发同步?是否只同步包含特定关键词的对话?
  • 标签规则 :自定义关键词列表,用于自动打标。 这些配置可以通过 chrome.storage.sync chrome.storage.local API进行持久化。

4. 部署、调试与常见问题排查

4.1 开发与调试流程

  1. 加载未打包的插件 :在Chrome中打开 chrome://extensions/ ,开启“开发者模式”,点击“加载已解压的扩展程序”,选择你的插件目录。
  2. 调试Content Script :在ChatGPT网页上右键“检查”,在开发者工具中,切换到“Sources”标签,在左侧导航栏找到“Content scripts”,这里可以看到你注入的脚本,并可以设置断点、查看Console。
  3. 调试Background Script :在 chrome://extensions/ 页面,找到你的插件,点击“service worker”链接(对于Manifest V3),会打开一个独立的开发者工具窗口。
  4. 调试Popup :点击插件图标,在弹出窗口上右键“检查”。

4.2 常见问题与解决方案实录

在实际开发和使用中,你几乎一定会遇到以下问题:

问题现象 可能原因 排查步骤与解决方案
插件无法捕获任何消息 1. 选择器失效。
2. MutationObserver 未正确绑定。
3. Content Script未注入。
1. 检查ChatGPT页面DOM结构是否已更新,调整选择器。 实操心得 :使用更通用的父容器选择器,或通过 data-* 属性定位,比依赖易变的CSS类名更稳定。
2. 在Content Script的Console中打印日志,确认脚本已执行,并检查 targetNode 是否正确找到。
3. 检查 manifest.json content_scripts matches 字段,确保包含了ChatGPT的域名( https://chat.openai.com/* )。
消息重复保存 1. MutationObserver 对同一内容变化触发了多次。
2. 插件重启后重复处理历史消息。
1. 在数据处理层增加去重逻辑,例如为每条消息生成一个唯一ID(基于时间戳+内容哈希),在推送前检查是否已存在。
2. 在Background Script中维护一个已处理消息ID的集合(存储在 chrome.storage 中),并在插件启动时初始化。
同步到Notion失败 1. API密钥无效或权限不足。
2. 数据库ID错误。
3. 请求速率超限。
4. 网络问题。
1. 在Notion集成的设置页面重新复制API Key,并确认已在目标数据库中邀请了该集成。
2. 仔细核对数据库ID(是数据库页面的URL中的长串哈希值,不是页面标题)。
3. Notion API有速率限制(约每秒3次请求)。需要在代码中实现简单的请求队列和延迟(例如使用 setTimeout p-limit 库)。
4. 检查Background Script的报错信息,网络请求需要正确的错误处理(try-catch)和重试机制。
自动生成的标签不准确 1. 关键词词典覆盖不全。
2. TF-IDF算法提取了无关的常用词。
1. 定期维护和更新你的技术关键词词典,可以分领域(前端、后端、运维)配置。
2. 在使用TF-IDF前,务必进行有效的 停用词过滤 (移除“的”、“了”、“如何”、“怎么”等无意义词)。对于中文,还需要高质量的分词库。 一个技巧 :结合规则匹配和简单算法,先匹配已知关键词,再用算法提取新词作为补充。
代码块格式丢失 1. 从DOM中提取代码内容时,只取了 innerText ,丢失了语言类型。
2. 目标知识库不支持Markdown代码块语法。
1. 提取时,要同时获取 pre code 标签上的类名(如 language-python )来确定语言。
2. 对于Notion,需要使用 code 类型的Block,并正确设置 language 属性。对于本地Markdown,确保使用正确的反引号语法。
插件在ChatGPT更新后失效 ChatGPT前端页面结构发生变化。 这是浏览器插件方案的固有风险。 建议 :将核心的选择器配置化,允许用户在插件设置中手动调整或选择“自动探测”模式。可以设计一个简单的“学习模式”,让用户点击页面上的消息,插件自动记录其选择器路径。

4.3 性能与体验优化建议

  1. 节流与防抖 MutationObserver 的回调可能被频繁触发。使用防抖函数(如Lodash的 _.debounce )确保只在对话停顿一段时间(如1.5秒)后才触发处理逻辑,避免不必要的性能消耗。
  2. 增量同步 :不要每次都将整个对话历史重新处理。只处理自上次同步以来新增的消息。这需要插件能持久化记录上次同步的位置(例如,最后一条已处理消息的ID或时间戳)。
  3. 提供手动同步按钮 :在插件Popup页面中提供一个“立即同步”按钮,给予用户控制权。同时,在ChatGPT网页的对话旁添加一个小的“保存到知识库”按钮(通过Content Script注入),用户体验会更佳。
  4. 错误反馈与日志 :在插件的Popup页面或一个独立的管理页面中,展示同步任务的历史记录和错误信息。这对于排查问题至关重要。
  5. 支持多知识库后端 :设计一个抽象的 Publisher 接口,让本地文件、Notion、语雀等不同实现都适配这个接口。这样未来扩展新的目标知识库会非常容易。

5. 扩展思路与高级玩法

基础功能实现后,你可以考虑以下方向来提升项目的价值:

5.1 对话内容的质量过滤与评分 不是所有对话都值得保存。可以引入简单的规则或模型来评分:

  • 规则过滤 :只保存AI回复长度超过一定阈值、或包含代码块、或用户提问中包含“总结”、“步骤”、“原理”等关键词的对话。
  • 模型评分 :使用一个轻量级的文本分类模型(或调用OpenAI的API本身),判断一段AI回复的“信息密度”或“知识价值”,低于阈值的不自动同步。

5.2 与本地向量数据库结合,实现智能检索 将保存的对话内容,通过嵌入模型(Embedding Model)转换为向量,存储到本地的ChromaDB或LanceDB中。这样,你可以在自己的知识库中,用自然语言提问,直接检索到历史上相关问题的ChatGPT解答,形成真正的“可检索记忆”。

5.3 支持更多AI平台和知识库 将数据采集模块抽象化,使其支持Claude、Gemini、Kimi等其他AI聊天平台。同时,增加对更多知识库(如语雀、Confluence、GitHub Wiki)的推送支持。

5.4 构建完整的桌面应用 将浏览器插件、本地文件服务、向量数据库、甚至一个简单的检索前端打包成一个跨平台的桌面应用(使用Electron或Tauri),提供更一体化的体验。

开发 lyw123www/chatgpt-to-kelivo 这类工具,最大的成就感来自于它切实地改变了你的工作流。它让那些原本散落在对话历史中的智慧碎片,得以规整、沉淀,并最终成为你个人知识体系中有机的一部分。这个过程本身,也是对你如何与AI协作、如何管理信息的一次深度思考和实践。从简单的脚本开始,逐步迭代,你会发现自己不仅在构建一个工具,更是在塑造一种更高效的学习和工作方式。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐