从原理到落地:RAG 技术深度拆解与 Java 实战全攻略

简介: RAG(检索增强生成)是解决大模型知识时效性差、易幻觉的核心方案:通过实时检索私有/外部数据,将其作为上下文输入大模型,实现准确、可更新的回答。相比微调,RAG成本低、上线快、维护简,是企业落地LLM的首选架构。

一、RAG:破解大模型「知识困境」的核心方案

大语言模型(LLM)凭借强大的语义理解和生成能力,成为当下技术领域的核心抓手,但实际落地中两个痛点始终无法回避:一是「知识时效性」,模型训练数据存在截止时间,无法获取最新信息;二是「幻觉问题」,模型可能生成不符合事实的内容,尤其在企业私有数据场景下,这两个问题直接制约了LLM的生产应用。

检索增强生成(Retrieval-Augmented Generation,RAG)正是为解决这些问题而生的技术架构——它将「检索」与「生成」结合,先从私有/外部数据源中检索与用户问题相关的信息,再将这些信息作为上下文传入大模型,让模型基于真实、最新的信息生成回答。相比模型微调,RAG无需重新训练模型,成本更低、更新更快,是企业落地LLM的首选方案。

二、RAG核心原理与流程拆解

2.1 核心流程

RAG的完整执行链路可拆解为6个核心步骤,各环节环环相扣,决定了最终回答的准确性和效率:

(1)文档加载

核心目标是将不同格式(PDF、TXT、Word、数据库等)的数据源,转化为程序可处理的文本格式。这一步的关键是兼容多源数据,同时保证文本提取的完整性(比如PDF的分页、格式还原)。

(2)文档分割

大模型的上下文窗口存在长度限制,且长文本直接传入会导致关键信息被稀释。文档分割需按「语义粒度」拆分(而非简单按字符数),比如按段落、章节拆分,既保证单段文本的语义完整性,又适配模型的上下文长度。

(3)文本向量化

将自然语言文本转化为机器可计算的向量(Embedding),向量的维度和表征能力直接影响检索精度。向量化的核心是通过预训练的嵌入模型,将文本的语义信息映射到高维向量空间,语义相似的文本,向量距离也更近。

(4)向量存储

将向量化后的文本片段存储到向量数据库(或简易的内存结构),方便后续快速检索。向量数据库需支持「相似性检索」(如余弦相似度、欧氏距离计算),常见的有Milvus、Pinecone、FAISS等,轻量场景也可使用Redis的向量扩展。

(5)检索相关文本

接收用户问题后,先将问题向量化,再从向量存储中检索出与问题语义最相似的文本片段(Top-N)。检索策略可优化,比如结合关键词检索+向量检索,提升召回率。

(6)构造提示词&生成回答

将检索到的文本片段作为「上下文」,与用户问题拼接成提示词,传入大模型。模型基于上下文生成回答,从根源上减少幻觉,保证回答的准确性。

2.2 RAG与微调的核心差异

维度 RAG 微调
知识更新 实时更新(修改数据源即可) 需重新训练/增量微调,周期长
成本 低(无需算力训练) 高(需GPU算力、数据标注)
适用场景 私有数据频繁更新、中小规模数据 通用知识固化、大规模专有数据
技术门槛 低(侧重工程实现) 高(需算法、训练经验)

三、实战准备:技术栈与环境搭建

3.1 技术栈选型

本次实战基于企业级Java技术栈,所有组件均选用稳定且主流的版本,兼顾兼容性和实用性:

  • 基础框架:Spring Boot 3.2.5(JDK 17)
  • 文档处理:Spring AI 1.0.0-M1(PDF读取)、Apache PDFBox 3.0.1
  • 大模型调用:RestTemplate(HTTP请求)、火山引擎LLM API
  • 工具类:Lombok 1.18.30、Spring Utils、FastJSON2 2.0.48、Guava 32.1.3-jre
  • 接口文档:SpringDoc OpenAPI 2.2.0(Swagger3)
  • 构建工具:Maven 3.9.6

3.2 Maven依赖配置

创建Maven项目,在pom.xml中引入以下依赖,确保版本兼容且无冲突:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

   <modelVersion>4.0.0</modelVersion>
   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>3.2.5</version>
       <relativePath/>
   </parent>
   <groupId>com.jam.demo</groupId>
   <artifactId>rag-demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>rag-demo</name>
   <description>RAG实战演示项目</description>
   
   <properties>
       <java.version>17</java.version>
       <fastjson2.version>2.0.48</fastjson2.version>
       <guava.version>32.1.3-jre</guava.version>
       <lombok.version>1.18.30</lombok.version>
       <springdoc.version>2.2.0</springdoc.version>
       <spring-ai.version>1.0.0-M1</spring-ai.version>
       <pdfbox.version>3.0.1</pdfbox.version>
   </properties>
   
   <dependencies>
       <!-- Spring Boot核心依赖 -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       
       <!-- Lombok -->
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <version>${lombok.version}</version>
           <scope>provided</scope>
       </dependency>
       
       <!-- Swagger3(SpringDoc) -->
       <dependency>
           <groupId>org.springdoc</groupId>
           <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
           <version>${springdoc.version}</version>
       </dependency>
       
       <!-- Spring AI(文档处理) -->
       <dependency>
           <groupId>org.springframework.ai</groupId>
           <artifactId>spring-ai-core</artifactId>
           <version>${spring-ai.version}</version>
       </dependency>
       <dependency>
           <groupId>org.springframework.ai</groupId>
           <artifactId>spring-ai-pdf-document-reader</artifactId>
           <version>${spring-ai.version}</version>
       </dependency>
       
       <!-- PDF处理增强 -->
       <dependency>
           <groupId>org.apache.pdfbox</groupId>
           <artifactId>pdfbox</artifactId>
           <version>${pdfbox.version}</version>
       </dependency>
       
       <!-- FastJSON2 -->
       <dependency>
           <groupId>com.alibaba.fastjson2</groupId>
           <artifactId>fastjson2</artifactId>
           <version>${fastjson2.version}</version>
       </dependency>
       
       <!-- Guava -->
       <dependency>
           <groupId>com.google.guava</groupId>
           <artifactId>guava</artifactId>
           <version>${guava.version}</version>
       </dependency>
       
       <!-- 测试依赖 -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
       </dependency>
   </dependencies>
   
   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
               <configuration>
                   <excludes>
                       <exclude>
                           <groupId>org.projectlombok</groupId>
                           <artifactId>lombok</artifactId>
                       </exclude>
                   </excludes>
               </configuration>
           </plugin>
       </plugins>
   </build>
   
   <!-- Spring AI仓库(M1版本需手动引入) -->
   <repositories>
       <repository>
           <id>spring-milestones</id>
           <name>Spring Milestones</name>
           <url>https://repo.spring.io/milestone</url>
           <snapshots>
               <enabled>false</enabled>
           </snapshots>
       </repository>
   </repositories>
</project>

3.3 配置文件(application.yml)

src/main/resources下创建application.yml,配置火山引擎LLM API信息、文件路径等核心参数:

spring:
 # 火山引擎LLM配置
 volc:
   api-key: your-volc-api-key  # 替换为实际API Key
   base-url: https://ark.cn-beijing.volces.com/api/v3/chat/completions  # 火山引擎API地址
   endpoint-id: your-endpoint-id  # 替换为实际模型端点ID
 # 文档路径配置
 doc:
   pdf-path: C:\\Users\\jamhi\\Downloads\\低代码开发师【初级】实战教程.pdf  # 替换为实际PDF路径

# 日志配置
logging:
 level:
   com.jam.demo: INFO
   org.springframework.web: WARN
 pattern:
   console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

# 服务器配置
server:
 port: 8080
 servlet:
   context-path: /rag-demo

四、核心模块实现:从文档加载到回答生成

4.1 文档加载工具类(DocLoadUtil.java)

封装PDF、TXT等文档的加载逻辑,保证文本提取的完整性,同时处理文件不存在、读取失败等异常:

package com.jam.demo.util;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.core.io.FileSystemResource;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;

/**
* 文档加载工具类
* 作者:ken
* 功能:支持PDF、TXT格式的文档加载,提取文本内容
*/

@Slf4j
public class DocLoadUtil {

   /**
    * 加载PDF文档并提取文本
    * @param pdfPath PDF文件绝对路径
    * @return 文档文本内容
    * @throws IOException 文件读取异常
    */

   public static String loadPdf(String pdfPath) throws IOException {
       // 参数校验
       StringUtils.hasText(pdfPath, "PDF文件路径不能为空");
       File pdfFile = new File(pdfPath);
       if (!pdfFile.exists()) {
           throw new IOException("PDF文件不存在:" + pdfPath);
       }
       
       // 方式1:基于Spring AI的PDF读取(简化版)
       PagePdfDocumentReader reader = new PagePdfDocumentReader(new FileSystemResource(pdfFile));
       List<Document> documents = reader.read();
       if (ObjectUtils.isEmpty(documents)) {
           log.warn("PDF文件内容为空:{}", pdfPath);
           return "";
       }
       
       // 拼接所有页面文本
       StringBuilder pdfContent = new StringBuilder();
       for (Document doc : documents) {
           String text = doc.getText();
           if (StringUtils.hasText(text)) {
               pdfContent.append(text);
           }
       }
       return pdfContent.toString();
   }

   /**
    * 加载TXT文档并提取文本
    * @param txtPath TXT文件绝对路径
    * @return 文档文本内容
    * @throws IOException 文件读取异常
    */

   public static String loadTxt(String txtPath) throws IOException {
       // 参数校验
       StringUtils.hasText(txtPath, "TXT文件路径不能为空");
       File txtFile = new File(txtPath);
       if (!txtFile.exists()) {
           throw new IOException("TXT文件不存在:" + txtPath);
       }
       
       // 按字符读取TXT内容
       char[] buffer = new char[1024];
       StringBuilder txtContent = new StringBuilder();
       try (FileReader reader = new FileReader(txtFile)) {
           int len;
           while ((len = reader.read(buffer)) != -1) {
               txtContent.append(buffer, 0, len);
           }
       }
       return txtContent.toString();
   }

   /**
    * 按语义分割文本(简易版)
    * @param content 原始文本
    * @param chunkSize 每个片段的最大字符数
    * @return 分割后的文本片段列表
    */

   public static List<String> splitText(String content, int chunkSize) {
       if (!StringUtils.hasText(content)) {
           return Lists.newArrayList();
       }
       if (chunkSize <= 0) {
           chunkSize = 1000; // 默认每段1000字符
       }
       
       List<String> chunks = Lists.newArrayList();
       int start = 0;
       int end = chunkSize;
       int contentLength = content.length();
       
       while (start < contentLength) {
           // 避免最后一段超出文本长度
           if (end > contentLength) {
               end = contentLength;
           }
           // 按段落分割(优先按换行符截断,保证语义完整)
           int splitIndex = content.lastIndexOf("\n", end);
           if (splitIndex == -1 || splitIndex < start) {
               splitIndex = end;
           }
           chunks.add(content.substring(start, splitIndex));
           start = splitIndex + 1;
           end = start + chunkSize;
       }
       return chunks;
   }
}

4.2 大模型调用工具类(LlmClientUtil.java)

封装火山引擎LLM API的调用逻辑,统一处理请求头、请求体构造,以及响应的安全解析:

package com.jam.demo.util;

import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Map;

/**
* 大模型调用工具类
* 作者:ken
* 功能:封装火山引擎LLM API的调用逻辑,处理请求与响应
*/

@Slf4j
public class LlmClientUtil {

   private static final RestTemplate REST_TEMPLATE = new RestTemplate();

   /**
    * 调用火山引擎LLM API生成回答
    * @param apiKey 火山引擎API Key
    * @param baseUrl API请求地址
    * @param endpointId 模型端点ID
    * @param prompt 拼接后的提示词(上下文+用户问题)
    * @return 大模型生成的回答
    * @throws Exception 调用异常
    */

   public static String callVolcLlm(String apiKey, String baseUrl, String endpointId, String prompt) throws Exception {
       // 参数校验
       StringUtils.hasText(apiKey, "API Key不能为空");
       StringUtils.hasText(baseUrl, "API请求地址不能为空");
       StringUtils.hasText(endpointId, "模型端点ID不能为空");
       StringUtils.hasText(prompt, "提示词不能为空");
       
       // 1. 构造请求头
       HttpHeaders headers = new HttpHeaders();
       headers.setContentType(MediaType.APPLICATION_JSON);
       headers.set("Authorization", "Bearer " + apiKey);
       
       // 2. 构造请求体
       Map<String, Object> params = Maps.newHashMap();
       params.put("model", endpointId);
       params.put("messages", List.of(Maps.newHashMap(
               "role", "user",
               "content", prompt
       )));
       
       // 3. 发送POST请求
       HttpEntity<Map<String, Object>> request = new HttpEntity<>(params, headers);
       ResponseEntity<Map> response = REST_TEMPLATE.postForEntity(baseUrl, request, Map.class);
       
       // 4. 安全解析响应(逐层判空,避免空指针)
       Map<String, Object> responseBody = response.getBody();
       if (ObjectUtils.isEmpty(responseBody)) {
           log.warn("LLM API返回空响应");
           return "未获取到有效回答";
       }
       
       List<Map<String, Object>> choices = (List<Map<String, Object>>) responseBody.get("choices");
       if (CollectionUtils.isEmpty(choices)) {
           log.warn("LLM API响应中无choices字段");
           return "未获取到有效回答";
       }
       
       Map<String, Object> firstChoice = choices.get(0);
       if (ObjectUtils.isEmpty(firstChoice)) {
           log.warn("LLM API响应中第一个choice为空");
           return "未获取到有效回答";
       }
       
       Map<String, Object> message = (Map<String, Object>) firstChoice.get("message");
       if (ObjectUtils.isEmpty(message)) {
           log.warn("LLM API响应中无message字段");
           return "未获取到有效回答";
       }
       
       String content = (String) message.get("content");
       if (!StringUtils.hasText(content)) {
           log.warn("LLM API响应中content字段为空");
           return "未获取到有效回答";
       }
       
       log.info("LLM API调用成功,生成回答长度:{}", content.length());
       return content;
   }
}

4.3 RAG核心控制器(RagChatController.java)

整合文档加载、提示词构造、大模型调用逻辑,提供REST接口,添加Swagger3注解,支持参数校验和异常处理:

package com.jam.demo.controller;

import com.jam.demo.util.DocLoadUtil;
import com.jam.demo.util.LlmClientUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
* RAG聊天控制器
* 作者:ken
* 功能:提供RAG增强的聊天接口,基于PDF文档回答用户问题
*/

@Slf4j
@RestController
@RequestMapping("/ragChat")
@Tag(name = "RAG聊天接口", description = "基于PDF文档的检索增强生成接口")
public class RagChatController {

   @Value("${spring.volc.api-key}")
   private String volcApiKey;

   @Value("${spring.volc.base-url}")
   private String volcBaseUrl;

   @Value("${spring.volc.endpoint-id}")
   private String volcEndpointId;

   @Value("${spring.doc.pdf-path}")
   private String pdfPath;

   /**
    * 基于PDF文档的RAG聊天接口
    * @param question 用户问题
    * @return 基于文档内容的回答
    */

   @GetMapping("/v2")
   @Operation(summary = "PDF文档RAG聊天", description = "传入用户问题,基于指定PDF文档内容生成回答")
   public String ragChat(
           @Parameter(description = "用户问题", required = true)

           @RequestParam String question) {
       // 参数校验
       if (!StringUtils.hasText(question)) {
           log.error("用户问题为空");
           return "用户问题不能为空";
       }
       
       try {
           // 1. 加载PDF文档内容
           String pdfContent = DocLoadUtil.loadPdf(pdfPath);
           if (!StringUtils.hasText(pdfContent)) {
               log.warn("PDF文档内容为空,路径:{}", pdfPath);
               return "文档内容为空,无法回答问题";
           }
           
           // 2. 分割文档(避免提示词过长)
           // 实际场景可根据模型上下文长度调整,这里暂不分割,直接拼接
           String prompt = "请基于以下文档内容回答用户问题,仅使用文档中的信息,不要编造内容:\n"
                   + "文档内容:\n" + pdfContent + "\n"
                   + "用户问题:" + question;
           
           // 3. 调用大模型生成回答
           return LlmClientUtil.callVolcLlm(volcApiKey, volcBaseUrl, volcEndpointId, prompt);
           
       } catch (Exception e) {
           log.error("RAG聊天接口调用失败", e);
           return "回答生成失败:" + e.getMessage();
       }
   }
}

4.4 启动类(RagDemoApplication.java)

配置Spring Boot启动类,排除不必要的自动配置(如数据库相关),减少资源占用:

package com.jam.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;

/**
* RAG实战项目启动类
* 作者:ken
*/

@SpringBootApplication(exclude = {
       // 排除数据库自动配置(无需数据库)
       DataSourceAutoConfiguration.class,
       JdbcTemplateAutoConfiguration.class
})
public class RagDemoApplication
{

   public static void main(String[] args) {
       SpringApplication.run(RagDemoApplication.class, args);
       log.info("RAG实战项目启动成功,访问地址:http://localhost:8080/rag-demo/swagger-ui/index.html");
   }
}

五、接口测试与问题排查

5.1 接口访问与测试

项目启动后,可通过以下方式测试接口:

  1. Swagger3文档:访问http://localhost:8080/rag-demo/swagger-ui/index.html,找到/ragChat/v2接口,传入用户问题(如“低代码开发师初级的核心知识点有哪些?”),点击执行即可获取回答。
  2. Postman/浏览器:访问http://localhost:8080/rag-demo/ragChat/v2?question=低代码开发师初级的核心知识点有哪些?,直接查看返回结果。 以下是返回截图:

5.2 常见问题与解决方案

(1)PDF读取乱码

  • 原因:PDF文件编码不兼容,或包含图片型文本(无法提取)。
  • 解决方案:
  • 对于编码问题:使用PDFBox的PDFTextStripper指定编码(如UTF-8);
  • 对于图片型PDF:集成OCR工具(如Tesseract),先识别图片文本再提取。

(2)大模型调用返回空内容

  • 原因:API Key/endpoint-id错误、请求体格式不合法、模型上下文长度超限。
  • 解决方案:
  • 校验API参数是否正确,可通过火山引擎控制台验证;
  • 拆分长文本,减少单次提示词长度;
  • 检查LlmClientUtil中的响应解析逻辑,确保字段名与API文档一致。

(3)接口调用超时

  • 原因:网络延迟、火山引擎API响应慢、文档加载耗时过长。
  • 解决方案:
  • RestTemplate设置超时时间:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(HttpClients.custom()
       .setConnectTimeout(5000)
       .setConnectionRequestTimeout(5000)
       .setSocketTimeout(10000)
       .build()));

  • 异步加载文档,缓存已加载的文档内容(如Redis),避免重复读取。

六、RAG底层逻辑深挖与优化

6.1 向量检索的核心:余弦相似度

文本向量化后,检索的核心是计算「问题向量」与「文档片段向量」的余弦相似度,公式如下:

  • 相似度取值范围为[-1,1],越接近1,语义越相似;
  • 实战中无需手动计算,向量数据库(如Milvus)已内置该算法,只需调用检索接口即可。

6.2 提示词工程优化

RAG的效果与提示词直接相关,以下是实战验证的优化技巧:

  1. 明确指令:在提示词中加入“仅使用文档中的信息回答,不要编造内容”,减少幻觉;
  2. 上下文排序:将与问题最相似的文档片段放在提示词前部,提升模型关注度;
  3. 精简上下文:只保留与问题相关的片段,避免无关信息稀释核心内容。

6.3 检索策略优化

单一的向量检索可能存在召回率不足的问题,可采用「混合检索」:

  1. 关键词检索:先通过ES/MySQL全文索引筛选出包含问题关键词的文档片段;
  2. 向量检索:对筛选后的片段做向量相似度排序,取Top-N;
  3. 结果融合:将两种检索结果融合,提升召回率和精度。

七、RAG扩展与进阶方向

7.1 多数据源接入

除了本地PDF,可扩展支持以下数据源:

  • 数据库:通过MyBatis Plus读取MySQL/PostgreSQL中的结构化数据;
  • 云存储:接入阿里云OSS、腾讯云COS,加载云端文档;
  • 网页:通过Jsoup爬取指定网页内容,补充数据源。

7.2 缓存层设计

文档加载和向量检索是耗时操作,可引入Redis缓存:

  1. 缓存已加载的文档文本(按文件路径为Key);
  2. 缓存已向量化的文档片段(按片段ID为Key);
  3. 缓存高频问题的检索结果(按问题哈希为Key)。

7.3 分布式部署

当文档量和请求量增大时,可采用分布式架构:

  • 文档加载服务:独立部署,负责多源文档的加载和分割;
  • 向量检索服务:独立部署,对接向量数据库,提供检索接口;
  • 大模型调用服务:独立部署,封装不同厂商的LLM API,实现多模型兼容。

八、总结

RAG并非复杂的算法创新,而是工程化的架构思路——它将「检索」的精准性与「生成」的灵活性结合,解决了大模型落地的核心痛点。从实战角度看,RAG的效果取决于三个核心:文档处理的完整性、检索的精准性、提示词的合理性。在企业落地中,无需追求“大而全”的架构,可从简单场景(如单PDF文档问答)切入,逐步扩展多数据源、缓存、分布式等能力。同时,需结合业务场景持续调优:比如ToB场景需注重回答的准确性和合规性,ToC场景需兼顾回答的流畅性和时效性。 RAG的价值不仅在于解决当下的问题,更在于为LLM落地提供了“低成本、快速迭代”的路径——企业无需投入巨额算力做微调,只需维护好数据源,就能让大模型持续输出有价值的内容。这也是RAG成为当前LLM落地主流方案的核心原因。

📦 本文配套源码已备好,评论区留个言,我发你邮箱!

目录
相关文章
|
21天前
|
人工智能 数据可视化 安全
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
本文详解如何用阿里云Lighthouse一键部署OpenClaw,结合飞书CLI等工具,让AI真正“动手”——自动群发、生成科研日报、整理知识库。核心理念:未来软件应为AI而生,CLI即AI的“手脚”,实现高效、安全、可控的智能自动化。
34907 56
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
|
15天前
|
人工智能 自然语言处理 安全
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
本文介绍了Claude Code终端AI助手的使用指南,主要内容包括:1)常用命令如版本查看、项目启动和更新;2)三种工作模式切换及界面说明;3)核心功能指令速查表,包含初始化、压缩对话、清除历史等操作;4)详细解析了/init、/help、/clear、/compact、/memory等关键命令的使用场景和语法。文章通过丰富的界面截图和场景示例,帮助开发者快速掌握如何通过命令行和交互界面高效使用Claude Code进行项目开发,特别强调了CLAUDE.md文件作为项目知识库的核心作用。
14116 43
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
|
3天前
|
缓存 人工智能 自然语言处理
我对比了8个Claude API中转站,踩了不少坑,总结给你
本文是个人开发者耗时1周实测的8大Claude中转平台横向评测,聚焦Claude Code真实体验:以加权均价(¥/M token)、内部汇率、缓存支持、模型真实性及稳定性为核心指标。
|
10天前
|
人工智能 JavaScript Ubuntu
低成本搭建AIP自动化写作系统:Hermes保姆级使用教程,长文和逐步实操贴图
我带着怀疑的态度,深度使用了几天,聚焦微信公众号AIP自动化写作场景,写出来的几篇文章,几乎没有什么修改,至少合乎我本人的意愿,而且排版风格,也越来越完善,同样是起码过得了我自己这一关。 这个其实OpenClaw早可以实现了,但是目前我觉得最大的区别是,Hermes会自主总结提炼,并更新你的写作技能。 相信就冲这一点,就值得一试。 这篇帖子主要就Hermes部署使用,作一个非常详细的介绍,几乎一步一贴图。 关于Hermes,无论你赞成哪种声音,我希望都是你自己动手行动过,发自内心的选择!
2811 28
|
1月前
|
人工智能 JSON 机器人
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
本文带你零成本玩转OpenClaw:学生认证白嫖6个月阿里云服务器,手把手配置飞书机器人、接入免费/高性价比AI模型(NVIDIA/通义),并打造微信公众号“全自动分身”——实时抓热榜、AI选题拆解、一键发布草稿,5分钟完成热点→文章全流程!
45823 158
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
|
6天前
|
弹性计算 人工智能 自然语言处理
阿里云Qwen3.6全新开源,三步完成专有版部署!
Qwen3.6是阿里云全新MoE架构大模型系列,稀疏激活显著降低推理成本,兼顾顶尖性能与高性价比;支持多规格、FP8量化、原生Agent及100+语言,开箱即用。
|
8天前
|
人工智能 弹性计算 安全
Hermes Agent是什么?怎么部署?超详细实操教程
Hermes Agent 是 Nous Research 于2026年2月开源的自进化AI智能体,支持跨会话持久记忆、自动提炼可复用技能、多平台接入与200+模型切换,真正实现“越用越懂你”。MIT协议,部署灵活,隐私可控。
2149 4