系列篇章💥

No. 文章
1 LangChain4j Java AI 应用开发实战(一):LangChain4j 快速入门指南
2 LangChain4j Java AI 应用开发实战(二):大模型参数调优实战:Temperature、TopP、MaxTokens 深度解析
3 LangChain4j Java AI 应用开发实战(三):多模态 AI 开发 - 图片理解与图像生成实战
4 LangChain4j Java AI 应用开发实战(四):提示词工程进阶 - 模板化与结构化 Prompt 设计
5 LangChain4j Java AI 应用开发实战(五):流式响应与对话记忆 - 提升用户体验的关键技术
6 LangChain4j Java AI 应用开发实战(六):声明式 AI Service - LangChain4j 的核心编程模型
7 LangChain4j Java AI 应用开发实战(七):结构化输出实战 - 从非结构化文本提取 POJO 对象


前言

大模型擅长生成自然语言,但程序需要的是结构化数据。如何让 AI 返回 JSON、Java 对象而非自由文本?LangChain4j 提供了强大的结构化输出能力,能自动将非结构化文本解析为枚举、数值、日期、POJO 等 Java 类型。本文将深入讲解 @Description 注解的字段级语义说明、JSON Mode 的强制结构化输出、以及复杂嵌套对象的提取技巧。你将学会如何从简历中提取人员信息、从评论中分析情感、从合同中抽取关键条款,让 AI 真正成为数据提取的利器,大幅提升业务自动化水平。


一、为什么需要结构化输出?

1.1 非结构化文本的痛点

传统 AI 调用返回的是自由文本

String response = chatModel.chat("从以下文本中提取姓名和年龄:张三今年25岁");
System.out.println(response);
// 输出:"姓名是张三,年龄是25岁。"

问题

  • 难以解析:需要用正则或 NLP 提取具体字段
  • 格式不稳定:每次回答格式可能不同
  • 无法直接使用:需要二次处理才能存入数据库
  • 容易出错:文本变化导致解析失败

1.2 结构化输出的优势

使用结构化输出后:

Person person = extractor.extractPerson("张三今年25岁");
System.out.println(person.getName());  // 张三
System.out.println(person.getAge());   // 25

优势

  • 类型安全:编译期检查,IDE 智能提示
  • 直接使用:无需解析,直接操作对象
  • 格式稳定:始终返回一致的 JSON 结构
  • 易于存储:可直接存入数据库或缓存

二、基础类型提取

2.1 枚举类型提取(情感分析)

static class Sentiment_Extracting_AI_Service_Example {

    enum Sentiment {
        POSITIVE, NEUTRAL, NEGATIVE
    }

    interface SentimentAnalyzer {

        /**
         * {{it}} 是特殊占位符,表示方法的第一个参数。
         */
        @UserMessage("Analyze sentiment of {{it}}")
        Sentiment analyzeSentimentOf(String text);

        /**
         * 返回 boolean 类型时,框架会将模型的 Yes/No 回答解析为 true/false。
         */
        @UserMessage("Does {{it}} have a positive sentiment?")
        boolean isPositive(String text);
    }

    public static void main(String[] args) {
        SentimentAnalyzer sentimentAnalyzer = AiServices.create(SentimentAnalyzer.class, model);

        Sentiment sentiment = sentimentAnalyzer.analyzeSentimentOf("It is good!");
        System.out.println(sentiment); // POSITIVE

        boolean positive = sentimentAnalyzer.isPositive("It is bad!");
        System.out.println(positive); // false
    }
}

工作原理

模型接收 Prompt → 从 [POSITIVE, NEUTRAL, NEGATIVE] 中选择
    ↓
输出:"POSITIVE"
    ↓
LangChain4j 匹配枚举值
    ↓
返回 Sentiment.POSITIVE

应用场景

  • 情感分析(正面/负面/中性)
  • 意图识别(查询/投诉/建议)
  • 风险评级(低/中/高)
  • 优先级分类(紧急/普通/低优)

2.2 列表枚举提取(多标签分类)

static class Hotel_Review_AI_Service_Example {

    public enum IssueCategory {
        MAINTENANCE_ISSUE,     // 维护问题
        SERVICE_ISSUE,         // 服务问题
        COMFORT_ISSUE,         // 舒适度问题
        FACILITY_ISSUE,        // 设施问题
        CLEANLINESS_ISSUE,     // 清洁度问题
        CONNECTIVITY_ISSUE,    // 网络连接问题
        CHECK_IN_ISSUE,        // 入住办理问题
        OVERALL_EXPERIENCE_ISSUE // 整体体验问题
    }

    interface HotelReviewIssueAnalyzer {

        // |||{{it}}||| 使用分隔符包裹文本
        @UserMessage("Please analyse the following review: |||{{it}}|||")
        List<IssueCategory> analyzeReview(String review);
    }

    public static void main(String[] args) {
        HotelReviewIssueAnalyzer analyzer = AiServices.create(HotelReviewIssueAnalyzer.class, model);

        String review = "Our stay at hotel was a mixed experience. The location was perfect... " +
                        "However, we encountered several issues. The air conditioning... " +
                        "Additionally, the room service was slow...";

        List<IssueCategory> issues = analyzer.analyzeReview(review);
        System.out.println(issues);
        // 输出:[MAINTENANCE_ISSUE, SERVICE_ISSUE, COMFORT_ISSUE, OVERALL_EXPERIENCE_ISSUE]
    }
}

关键点

  • 返回 List<Enum> 支持多标签分类
  • 一个样本可同时属于多个类别
  • 使用分隔符 ||| 帮助模型识别待分析内容

2.3 数值类型提取

static class Number_Extracting_AI_Service_Example {

    interface NumberExtractor {

        @UserMessage("Extract number from {{it}}")
        int extractInt(String text);

        @UserMessage("Extract number from {{it}}")
        long extractLong(String text);

        @UserMessage("Extract number from {{it}}")
        BigInteger extractBigInteger(String text);

        @UserMessage("Extract number from {{it}}")
        float extractFloat(String text);

        @UserMessage("Extract number from {{it}}")
        double extractDouble(String text);

        @UserMessage("Extract number from {{it}}")
        BigDecimal extractBigDecimal(String text);
    }

    public static void main(String[] args) {
        NumberExtractor extractor = AiServices.create(NumberExtractor.class, model);

        String text = "After countless millennia of computation, the supercomputer Deep Thought finally announced "
                + "that the answer to the ultimate question of life, the universe, and everything was forty two.";

        int intNumber = extractor.extractInt(text);
        System.out.println(intNumber); // 42

        double doubleNumber = extractor.extractDouble(text);
        System.out.println(doubleNumber); // 42.0

        BigDecimal bigDecimalNumber = extractor.extractBigDecimal(text);
        System.out.println(bigDecimalNumber); // 42.0
    }
}

支持的数值类型

类型 适用场景 示例输入 输出
int 整数 “二十五岁” 25
long 大整数 “订单号1234567890” 1234567890L
float/double 浮点数 “价格99.99元” 99.99
BigDecimal 高精度小数 “金额1,234.56元” 1234.56
BigInteger 超大整数 “天文数字” 大数

智能解析

  • ✅ 阿拉伯数字:“42” → 42
  • ✅ 中文数字:“四十二” → 42
  • ✅ 英文数字:“forty two” → 42
  • ✅ 带单位:“99.99元” → 99.99

2.4 日期时间提取

static class Date_and_Time_Extracting_AI_Service_Example {

    interface DateTimeExtractor {

        @UserMessage("Extract date from {{it}}")
        LocalDate extractDateFrom(String text);

        @UserMessage("Extract time from {{it}}")
        LocalTime extractTimeFrom(String text);

        @UserMessage("Extract date and time from {{it}}")
        LocalDateTime extractDateTimeFrom(String text);
    }

    public static void main(String[] args) {
        DateTimeExtractor extractor = AiServices.create(DateTimeExtractor.class, model);

        String text = "The tranquility pervaded the evening of 1968, just fifteen minutes shy of midnight,"
                + " following the celebrations of Independence Day.";

        LocalDate date = extractor.extractDateFrom(text);
        System.out.println(date); // 1968-07-04

        LocalTime time = extractor.extractTimeFrom(text);
        System.out.println(time); // 23:45

        LocalDateTime dateTime = extractor.extractDateTimeFrom(text);
        System.out.println(dateTime); // 1968-07-04T23:45
    }
}

智能解析能力

  • ✅ “1968年独立日” → 1968-07-04(美国独立日是7月4日)
  • ✅ “差15分钟到午夜” → 23:45
  • ✅ “明天下午3点” → 相对日期计算
  • ✅ “下周一” → 自动推算日期

三、POJO 对象提取

3.1 基础 POJO 提取

static class POJO_Extracting_AI_Service_Example {

    static class Person {

        @Description("first name of a person")
        private String firstName;
        
        private String lastName;
        
        private LocalDate birthDate;

        @Override
        public String toString() {
            return "Person {" +
                    " firstName = \"" + firstName + "\"" +
                    ", lastName = \"" + lastName + "\"" +
                    ", birthDate = " + birthDate +
                    " }";
        }
    }

    interface PersonExtractor {

        @UserMessage("Extract a person from the following text: {{it}}")
        Person extractPersonFrom(String text);
    }

    public static void main(String[] args) {
        // 提取 POJO 时启用 JSON Mode
        ChatModel model = OpenAiChatModel.builder()
                .baseUrl("http://langchain4j.dev/demo/openai/v1")
                .modelName("gpt-4o-mini")
                .apiKey("demo")
                .responseFormat("json_object")  // 强制 JSON 输出
                .timeout(ofSeconds(60))
                .build();

        PersonExtractor extractor = AiServices.create(PersonExtractor.class, model);

        String text = "In 1968, amidst the fading echoes of Independence Day, "
                + "a child named John arrived under the calm evening sky. "
                + "This newborn, bearing the surname Doe, marked the start of a new journey.";

        Person person = extractor.extractPersonFrom(text);
        System.out.println(person); 
        // Person { firstName = "John", lastName = "Doe", birthDate = 1968-07-04 }
    }
}

核心要素

(1)@Description 注解

@Description("first name of a person")
private String firstName;

作用

  • 为字段添加语义说明
  • 帮助模型理解如何提取
  • 提升提取准确率

何时使用

  • ✅ 字段名不够清晰(如 name1, value
  • ✅ 需要额外约束(如格式、范围)
  • ✅ 多义词需要澄清

(2)JSON Mode

.responseFormat("json_object")

作用

  • 强制模型输出合法 JSON
  • 避免自由文本格式
  • 提高解析成功率

可选值

说明 适用场景
text 自由文本(默认) 对话、创意写作
json_object JSON 对象 POJO 提取
json_schema 严格 JSON Schema 复杂结构、生产环境

3.2 复杂 POJO 提取(带描述的食谱生成)

static class POJO_With_Descriptions_Extracting_AI_Service_Example {

    static class Recipe {

        @Description("short title, 3 words maximum")
        private String title;

        @Description("short description, 2 sentences maximum")
        private String description;

        @Description("each step should be described in 6 to 8 words, steps should rhyme")
        private List<String> steps;

        private Integer preparationTimeMinutes;

        @Override
        public String toString() {
            return "Recipe {" +
                    " title = \"" + title + "\"" +
                    ", description = \"" + description + "\"" +
                    ", steps = " + steps +
                    ", preparationTimeMinutes = " + preparationTimeMinutes +
                    " }";
        }
    }

    interface Chef {

        Recipe createRecipeFrom(String... ingredients);
    }

    public static void main(String[] args) {
        ChatModel model = OpenAiChatModel.builder()
                .baseUrl("http://langchain4j.dev/demo/openai/v1")
                .modelName("gpt-4o-mini")
                .apiKey("demo")
                .responseFormat("json_object")
                .timeout(ofSeconds(60))
                .build();

        Chef chef = AiServices.create(Chef.class, model);

        Recipe recipe = chef.createRecipeFrom("cucumber", "tomato", "feta", "onion", "olives", "lemon");

        System.out.println(recipe);
        // Recipe {
        //   title = "Greek Salad",
        //   description = "A refreshing mix of veggies and feta cheese in a zesty dressing.",
        //   steps = [
        //     "Chop cucumber and tomato",
        //     "Add onion and olives",
        //     "Crumble feta on top",
        //     "Drizzle with dressing and enjoy!"
        //   ],
        //   preparationTimeMinutes = 10
        // }
    }
}

@Description 的高级用法

@Description("short title, 3 words maximum")
private String title;

效果

  • 约束输出长度
  • 指定格式要求
  • 引导模型风格

更多示例

@Description("phone number in format XXX-XXXX-XXXX")
private String phone;

@Description("email address, must contain @ symbol")
private String email;

@Description("rating from 1 to 5 stars")
private int rating;

@Description("list of tags, maximum 5 items")
private List<String> tags;

3.3 嵌套 POJO 提取

虽然示例代码中未展示,但 LangChain4j 支持嵌套对象提取:

@Data
public class Address {
    
    @Description("省份")
    private String province;
    
    @Description("城市")
    private String city;
    
    @Description("详细地址")
    private String street;
    
    @Description("邮政编码")
    private String zipCode;
}

@Data
public class Employee {
    
    @Description("员工姓名")
    private String name;
    
    @Description("年龄")
    private int age;
    
    @Description("邮箱地址")
    private String email;
    
    @Description("居住地址")
    private Address address;  // 嵌套对象
    
    @Description("联系电话列表")
    private List<String> phones;  // 列表字段
}

interface EmployeeExtractor {
    
    @UserMessage("从以下文本中提取员工信息:{{text}}")
    Employee extractEmployee(@V("text") String text);
}

public class NestedPOJOExample {
    
    public static void main(String[] args) {
        
        ChatModel model = OpenAiChatModel.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .modelName("gpt-4o-mini")
            .responseFormat("json_object")
            .build();

        EmployeeExtractor extractor = AiServices.create(EmployeeExtractor.class, model);

        String text = "张三,28岁,邮箱zhangsan@example.com,住在北京市朝阳区长安街100号,邮编100000,电话13800138000和13900139000";
        
        Employee employee = extractor.extractEmployee(text);
        
        System.out.println(employee.getName());           // 张三
        System.out.println(employee.getAddress().getCity()); // 北京
        System.out.println(employee.getPhones().size());  // 2
    }
}

关键点

  • ✅ 支持任意深度的嵌套
  • ✅ 每个嵌套对象都可使用 @Description
  • ✅ 列表字段支持 List<POJO>

四、JSON Mode 详解

4.1 为什么需要 JSON Mode?

不使用 JSON Mode

模型输出:
"根据文本分析,这个人叫张三,年龄25岁。"

解析失败:不是合法 JSON

使用 JSON Mode

模型输出:
{
  "name": "张三",
  "age": 25
}

解析成功:直接映射到 Java 对象

4.2 三种响应格式对比

格式 说明 优点 缺点
text 自由文本 灵活、自然 难以解析
json_object JSON 对象 简单易用 无 Schema 验证
json_schema 严格 JSON Schema 强验证、高可靠 部分模型不支持

4.3 json_object vs json_schema

(1)json_object(推荐大多数场景)

ChatModel model = OpenAiChatModel.builder()
    .apiKey(System.getenv("OPENAI_API_KEY"))
    .modelName("gpt-4o-mini")
    .responseFormat("json_object")  // 简单 JSON 模式
    .build();

特点

  • ✅ 所有 GPT 模型支持
  • ✅ 配置简单
  • ✅ 适合大多数场景
  • ❌ 不验证字段名称和类型

(2)json_schema(生产环境推荐)

ChatModel model = OpenAiChatModel.builder()
    .apiKey(System.getenv("OPENAI_API_KEY"))
    .modelName("gpt-4o")
    .responseFormat("json_schema")  // 严格 Schema 模式
    .strictJsonSchema(true)
    .build();

特点

  • ✅ 严格验证 JSON 结构
  • ✅ 字段名称、类型必须匹配
  • ✅ 可靠性最高
  • ❌ 仅 GPT-4o 及更新模型支持
  • ❌ 演示端点可能不完全支持

五、实战案例:简历信息提取系统

5.1 需求

从简历文本中提取结构化信息,包括:

  • 个人信息(姓名、年龄、联系方式)
  • 教育背景(学校、专业、学历)
  • 工作经历(公司、职位、时间)
  • 技能清单

5.2 完整代码

(1)定义 POJO

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Education {
    
    @Description("学校名称")
    private String school;
    
    @Description("专业名称")
    private String major;
    
    @Description("学历(本科/硕士/博士)")
    private String degree;
    
    @Description("毕业年份")
    private Integer graduationYear;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class WorkExperience {
    
    @Description("公司名称")
    private String company;
    
    @Description("职位名称")
    private String position;
    
    @Description("开始时间(YYYY-MM)")
    private String startDate;
    
    @Description("结束时间(YYYY-MM,至今填\"至今\")")
    private String endDate;
    
    @Description("工作描述,简要说明职责和成就")
    private String description;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Resume {
    
    @Description("候选人姓名")
    private String name;
    
    @Description("年龄")
    private Integer age;
    
    @Description("手机号码")
    private String phone;
    
    @Description("邮箱地址")
    private String email;
    
    @Description("教育背景列表,按时间倒序")
    private List<Education> educations;
    
    @Description("工作经历列表,按时间倒序")
    private List<WorkExperience> experiences;
    
    @Description("技能清单,如 Java、Spring Boot、MySQL 等")
    private List<String> skills;
}

(2)定义 AI Service

@AiService
public interface ResumeExtractor {

    @SystemMessage("""
        你是专业的简历信息提取助手。
        
        任务:
        1. 从简历文本中提取结构化信息
        2. 保持信息准确,不要编造
        3. 如果某项信息不存在,填 null
        4. 日期格式统一为 YYYY-MM
        """)
    @UserMessage("请从以下简历中提取信息:\n\n{{resumeText}}")
    Resume extractResume(@V("resumeText") String resumeText);
}

(3)Service 层

@Service
public class ResumeExtractionService {

    @Autowired
    private ResumeExtractor resumeExtractor;

    public Resume extractResume(String resumeText) {
        
        // 输入校验
        if (resumeText == null || resumeText.length() < 50) {
            throw new IllegalArgumentException("简历文本过短,无法提取");
        }
        
        try {
            return resumeExtractor.extractResume(resumeText);
        } catch (Exception e) {
            throw new ServiceException("简历提取失败:" + e.getMessage(), e);
        }
    }
}

(4)Controller 层

@RestController
@RequestMapping("/api/resume")
public class ResumeController {

    @Autowired
    private ResumeExtractionService resumeService;

    @PostMapping("/extract")
    public ResponseEntity<Resume> extractResume(@RequestBody Map<String, String> request) {
        
        String resumeText = request.get("text");
        Resume resume = resumeService.extractResume(resumeText);
        
        return ResponseEntity.ok(resume);
    }
}

(5)使用示例

# 请求
curl -X POST http://localhost:8080/api/resume/extract \
  -H "Content-Type: application/json" \
  -d '{
    "text": "张三,28岁,电话13800138000,邮箱zhangsan@example.com。\n\n教育背景:\n2014-2018 北京大学 计算机科学与技术 本科\n2018-2021 清华大学 软件工程 硕士\n\n工作经历:\n2021-07 至今 阿里巴巴 Java开发工程师 负责电商平台后端开发\n2018-07 至 2018-12 腾讯 实习工程师 参与微信小程序开发\n\n技能:Java, Spring Boot, MySQL, Redis, Docker"
  }'

# 响应
{
  "name": "张三",
  "age": 28,
  "phone": "13800138000",
  "email": "zhangsan@example.com",
  "educations": [
    {
      "school": "清华大学",
      "major": "软件工程",
      "degree": "硕士",
      "graduationYear": 2021
    },
    {
      "school": "北京大学",
      "major": "计算机科学与技术",
      "degree": "本科",
      "graduationYear": 2018
    }
  ],
  "experiences": [
    {
      "company": "阿里巴巴",
      "position": "Java开发工程师",
      "startDate": "2021-07",
      "endDate": "至今",
      "description": "负责电商平台后端开发"
    },
    {
      "company": "腾讯",
      "position": "实习工程师",
      "startDate": "2018-07",
      "endDate": "2018-12",
      "description": "参与微信小程序开发"
    }
  ],
  "skills": ["Java", "Spring Boot", "MySQL", "Redis", "Docker"]
}

六、常见问题与避坑指南

6.1 字段提取不准确

现象

@Description("姓名")
private String name;

// 输入:"我叫张三"
// 输出:name = "我叫张三"  ← 包含了多余文字

解决方案:优化 @Description

@Description("仅提取姓名,不包含'我叫'等前缀")
private String name;

6.2 JSON 解析失败

现象

com.fasterxml.jackson.databind.JsonMappingException: 
Unexpected token (START_ARRAY), expected START_OBJECT

原因:模型返回了数组而非对象

解决方案

  1. 明确 Prompt
@UserMessage("请以 JSON 对象格式返回,不要返回数组或其他格式:{{text}}")
  1. 启用 JSON Mode
.responseFormat("json_object")
  1. 捕获异常并重试
try {
    return extractor.extract(text);
} catch (Exception e) {
    logger.warn("提取失败,重试中...", e);
    return extractor.extract(text);  // 重试一次
}

6.3 嵌套对象提取失败

现象

嵌套字段为 null

原因

  • 模型不理解嵌套结构
  • JSON Schema 过于复杂

解决方案

  1. 简化嵌套层级
// ❌ 三层嵌套
class A { B b; }
class B { C c; }
class C { String value; }

// ✅ 扁平化
class A {
    String bValue;
    String cValue;
}
  1. 分步提取
// 第一步:提取基本信息
Person person = extractor.extractPerson(text);

// 第二步:提取地址
Address address = extractor.extractAddress(text);

// 手动组装
person.setAddress(address);

6.4 性能问题

现象

POJO 提取耗时 5-10 秒

原因

  • JSON Mode 增加推理时间
  • 复杂 Schema 计算量大

解决方案

  1. 使用更快的模型
.modelName("gpt-4o-mini")  // 比 gpt-4o 快 50%
  1. 异步处理
CompletableFuture<Resume> future = CompletableFuture.supplyAsync(() -> 
    resumeExtractor.extractResume(text)
);

// 继续处理其他任务
// ...

Resume resume = future.get();  // 需要时再获取结果
  1. 缓存结果
@Cacheable(value = "resumes", key = "#text.hashCode()")
public Resume extractResume(String text) {
    return resumeExtractor.extractResume(text);
}

七、最佳实践

7.1 @Description 设计原则

好的 Description

@Description("手机号码,11位数字,格式:1XXXXXXXXXX")
private String phone;

@Description("评分,1-5之间的整数,5分为最高")
private int rating;

@Description("邮箱地址,必须包含 @ 符号")
private String email;

原则

  • 明确格式要求
  • 指定取值范围
  • 提供示例(必要时)

差的 Description

@Description("电话")  // 太模糊
private String phone;

@Description("数据")  // 无意义
private Object data;

7.2 模型选择策略

场景 推荐模型 原因
简单提取(姓名、年龄) gpt-4o-mini 成本低、速度快
复杂 POJO(嵌套对象) gpt-4o 理解能力强
高精度要求(金融、医疗) gpt-4o + json_schema 最可靠
批量处理(千级以上) gpt-4o-mini 成本可控

7.3 错误处理策略

@Service
public class RobustExtractor {

    @Autowired
    private ResumeExtractor extractor;

    public Resume extractWithRetry(String text, int maxRetries) {
        
        for (int i = 0; i < maxRetries; i++) {
            try {
                Resume resume = extractor.extractResume(text);
                
                // 验证结果
                if (validateResume(resume)) {
                    return resume;
                }
                
                logger.warn("第 {} 次提取结果无效,重试中...", i + 1);
                
            } catch (Exception e) {
                logger.warn("第 {} 次提取失败:{}", i + 1, e.getMessage());
            }
        }
        
        throw new ServiceException("多次提取失败,请检查输入文本");
    }

    private boolean validateResume(Resume resume) {
        // 基本验证
        return resume.getName() != null && !resume.getName().isEmpty();
    }
}

结语

通过本文的学习,你已经掌握了 LangChain4j 结构化输出的核心技术。从基础的枚举、数值、日期提取,到复杂的嵌套 POJO 解析,再到 JSON Mode 的强制结构化输出,这些技术能让 AI 从"聊天机器人"升级为"数据提取引擎"。记住,好的结构化输出依赖三个要素:清晰的 @Description 字段说明、合适的 JSON Mode 配置、以及健壮的错误处理机制。在实际项目中,建议优先使用 json_object 模式平衡性能与可靠性,对于金融、医疗等高精度场景再考虑 json_schema。


在这里插入图片描述

🎯🔖更多专栏系列文章:AI大模型提示工程完全指南AI大模型探索之路(零基础入门)AI大模型预训练微调进阶AI大模型开源精选实践AI大模型Spring AI开发实战🔥🔥🔥 其他专栏可以查看博客主页

🔔 关于作者:资深程序老猿,10年+架构经验,现专注 AIGC 探索与实践。
👍 若文章对你有所触动,恳请点赞 ⭐ 关注 ⭐ 收藏!AI 浪潮已至,愿与你同行。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐