SpringAI个人学习笔记

聊天客户端 ChatClient

chatClient 是 SpringAI 框架中用于与 AI 模型进行对话交互的主入口,其封装了以下的逻辑:

  • 提示词(Prompt)构建与模板化
  • 多轮对话上下文管理(CahtMemory)
  • 请求/响应的序列化与反序列化
  • 同步/流式调用支持
  • 模型无关的统一接口
  • Advisors 扩展机制

ChatClient 核心 API

链式构建+函数式调用

构建阶段(Builder 配置)

定义 ChatClient 的全局默认行为(一次配置,多次复用);实际编写代码可放在一个配置类中使用

.defaultSystem(String systemMessage)

设置所有对话默认的系统提示词

注意:可被实际调用中的.system()覆盖

.defaultAdvisors(Advisor...advisors)

注册全局默认的 Advisor(记忆、日志、函数调用等),所有通过该 ChatClient 发起请求都会应用这些 Advisor

示例:

.defaultAdvisors( new SimpleLoggerAdvisor(), new MessageChatMemoryAdvisor(chatMemory) )

.defaultTools(Tool ...tools)

注册全局默认工具(Function Calling)

.defaultFunctions(List<String> functionNames)

显示指定默认启用哪些函数,适用于已有注册工具但只想开放部分

.defaultOptions(ChatOptions options)

用于设置底层模型通用参数

示例:

.defaultOptions(OpenAiChatOptions.builder() .withTemperature(0.7) .withMaxTokens(1000) .build())

参数说明:

1.temperature(温度)——控制生成文本的随机性/创造性 0.0-2.0

说明

低值:模型更保守、更确定、可预测,适合事实问答,代码生成等场景

高值:模型更随机、多样、有创意,适合创作、头脑风暴等场景

2.maxTokens(最大生成长度)——限制模型单次回复最多生成多少个 token

说明

输出部分的最大长度

调用阶段(Prompt 链

定义单次对话的具体内容和参数(每次请求动态设置);实际编写代码可放在对应控制器中使用

prompt()

说明:启动一次对话构建流程。所有消息(system/user/assistant)和参数在此设置

.system(String content)

设置系统消息(角色设定,行为约束)

注意:可多次调用,按顺序加入消息列表

.user(String content)

设置用户消息(即当前轮次的用户输入)

注意:必须调用!!!只调用一次

.advisors(Consumer<AdvisorSpec>)

注入运行时参数或行为增强

关键用途:通过 param(...)传入 converstaionId,实现多对话隔离

.advisors(a -> a.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, chatId))

.call()

执行同步非流式调用,返回 ChatResponse

.stream()

执行响应式流式调用,返回 Flux<ChatResponse>

区分流式与非流式:非流式就是一次性给出所有消息,流式就是一个字一个字的生成给出

.content()

从 ChatResponse 中快捷提取纯文本回复内容

等价于 response.getResult().getOutput().getContent()

.functions(List<Tool> tools)

为本次调用临时指定可用工具

注意:会覆盖默认的工具defaultTools()

实现最简单的 AI 文本对话(忽略依赖导入)

1.配置类

@Configuration public class SpringAiConfig { @Bean public ChatMemory chatMemory() { return new InMemoryChatMemory(); } @Bean public ChatClient chatClient(OpenAiChatModel chatModel, ChatMemory chatMemory) { return ChatClient.builder(chatModel) .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory)) .build(); } }

2.控制器

@RestController @RequestMapping("/ai") public class ChatController { private final ChatClient chatClient; public ChatController(ChatClient chatClient) { this.chatClient = chatClient; } @GetMapping("/chat") public String chat(@RequestParam String prompt, @RequestParam String chatId) { return chatClient.prompt() .user(prompt) .advisors(a -> a.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)) .call() .content(); } }

聊天记忆

What is Chat Memory?

聊天记忆是一种机制,用于存储和管理用户与 AI 助手之间对话历史,能让 AI 记住之前的对话内容,在后续的聊天交互中保持上下文的连贯性

Why need Chat Memory?

为了保持上下文的连续性,避免用户每次重新输入一些重复信息,提高用户的体验,解决复杂任务需要多轮交互对话完成的问题。

SpringAI 的 ChatMemory 封装

ChatMemory 接口

定义了聊天记忆的基本操作规范,包括添加,获取,删除消息的方法

// 添加消息 chatMemory.add("session123", userMessage); chatMemory.add("session123", aiResponse); // 获取最近的N条消息作为上下文 List<Message> recentMessages = chatMemory.get("session123", 10); // 清除特定会话 chatMemory.remove("session123"); 

InMemoryChatMemory 实现类——基于内存的聊天记忆实现

JdbcChatMemoryRepository 实现类——基于关系型数据库的聊天记忆实现

消息顾问—— MessageChatMemoryAdvisor

在请求前后自动处理消息的存储与检索

public class MessageChatMemoryAdvisor extends AbstractChatMemoryAdvisor { @Override public ChatModelRequestInterceptor.Result intercept(ChatModelRequest request, Map<String, Object> attributes) { // 1. 在请求发送前执行 String conversationId = getConversationId(attributes); // 2. 从记忆中获取历史消息 List<Message> historyMessages = chatMemory.get(conversationId, maxMessages); // 3. 将历史消息插入到请求的前面 List<Message> allMessages = new ArrayList<>(); allMessages.addAll(historyMessages); // 先添加历史消息 allMessages.addAll(request.getMessages()); // 再添加当前消息 return ChatModelRequestInterceptor.Result.just( ChatModelRequest.builder() .messages(allMessages) .options(request.getOptions()) .build() ); } @Override public ChatModelResponseInterceptor.Result intercept(ChatModelResponse response, Map<String, Object> attributes) { // 4. 请求完成后执行:保存用户消息和AI响应到记忆中 String conversationId = getConversationId(attributes); // 保存用户的问题 List<Message> originalMessages = (List<Message>) attributes.get("originalMessages"); for (Message msg : originalMessages) { chatMemory.add(conversationId, msg); } // 保存AI的回答 String aiResponse = response.getResult().getOutput().getContent(); chatMemory.add(conversationId, new AssistantMessage(aiResponse)); return ChatModelResponseInterceptor.Result.just(response); } } 

SpringAI 聊天记忆实现原理

实现机制

1.会话标识:使用conversationId区分不同的对话会话

2.消息存储:将用户消息和AI响应按顺序存储

3.上下文注入:在每次请求时,将历史消息作为上下文传递给AI模型

4.自动管理:通过advisor自动处理消息的存取

完整对话流程示例

第一次对话 (chatId = "user123"):

User: "你好"

System: 添加历史 -> [User: "你好"]

AI: "您好!我是小膳"

System: 保存响应 -> [User: "你好", Assistant: "您好!我是小膳"]

第二次对话 (chatId = "user123"):

User: "我想减肥"

System:

1. 从记忆获取历史: [User: "你好", Assistant: "您好!我是小膳"]

2. 构造完整请求: [User: "你好", Assistant: "您好!我是小膳", User: "我想减肥"]

3. 发送给AI

AI: "好的,根据您的情况..."

System: 保存到记忆 -> [User: "你好", Assistant: "您好!我是小膳", User: "我想减肥", Assistant: "好的,根据您的情况..."]

最小化实现示例

1.配置类

@Configuration public class AiConfig { @Bean public ChatMemory chatMemory() { return new InMemoryChatMemory(); // 支持多 conversationId } @Bean public ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory) { return ChatClient.builder(chatModel) .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory)) .build(); } }

2.控制器

@RestController public class SimpleChatController { private final ChatClient chatClient; public SimpleChatChatController(ChatClient chatClient) { this.chatClient = chatClient; } // 示例:GET /chat?prompt=你好&chatId=user123 @GetMapping("/chat") public String chat(@RequestParam String prompt, @RequestParam String chatId) { return chatClient.prompt() .user(prompt) .advisors(a -> a.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)) .call() .content(); } // 查看历史 @GetMapping("/history/{chatId}") public List<Message> history(@PathVariable String chatId, ChatMemory chatMemory) { return chatMemory.get(chatId, 100); // 最多100条 } }

提示词

四大角色

系统角色

解释:系统的全局设定(比如是一个资深营养师、一位专业教师、一位创作诗人)

作用:设定模型全局行为、身份、规则或上下文

特点:对用户不可见(通常),但是强烈影响模型输出

用户角色

解释:就是用户,真人输入

作用:代表人类用户的输入或请求

特点:触发模型响应的起点

助理角色

解释:就是 AI 的回答,回复

作用:代表模型自身的回复

特点:是模型生成的内容;在多轮对话中会被记录,用于上下文记忆

工具/功能角色

解释:就是使用工具调用返回结果

作用:表示外部工具的返回结果

如何写好一份提示词——核心要素

1.明确目标

清楚模型需要完成什么任务

2.提供上下文(外部背景)

给出必要的背景信息,帮助模型理解任务场景。

3.具体指令

使用直接、明确的语言告诉模型做什么和怎么做

4.格式要求

指定输出格式

5.约束条件

包括字数限制、语气风格、避免的内容、语言种类、技术深度等等

6.示例

提供几个输入-输出示例,帮助模型理解期望输出的样式

通用模版结构

【角色设定】你是一位[角色,如资深科技编辑/Python开发者/高中物理老师]。

【任务目标】请[具体任务,如撰写一篇关于AI伦理的短文]。

【目标受众】面向[读者群体,如普通公众/高中生/企业高管]。

【内容要求】涵盖以下要点: - 要点1 - 要点2 - …

【格式要求】以[格式,如三段式结构/项目符号列表/JSON格式]输出。

【风格与语气】使用[语气,如专业但易懂/轻松幽默/严谨学术]的语气。

【其他约束】字数控制在[数字]字以内;避免使用专业术语;使用中文简体。

结构化输出

在没有结构化输出时,用户在与大模型交互时,对其说“我今天吃了牛肉炒饭,特别香,就是有点咸”,大模型回复内容可能会是“看起来你挺喜欢这碗牛肉炒饭,下次可以少放点盐”这种自由文本固然挺自然的,但是程序是很难直接提取关键的信息,当使用结构化输出时,就相当于告诉大模型:“请用固定格式告诉我:吃的什么、好吃吗、咸不咸?”于是大模型就会严格按照这个格式返回,比如:

{ "food":"牛肉炒饭", "taste":"好吃", "tooSalty":true }

在经历结构化输出之后,应用就能很方便的将“牛肉炒饭”数据记入饮食记录,由“tooSalty:true”触发提醒“今日钠摄入可能偏高”,而省去了分析一大段文字。

即:让 AI 的回答变成“机器能直接用的数据”,而不是“人读起来舒服的话”。

概念

结构化输出是指通过大语言模型生成符合预定义数据格式(如 Java 对象,JSON Schema 等)的响应,而非自由文本。目标是确保 LLM 的输出可被程序直接解析和使用,提升系统集成的可靠性与类型安全性,Spring AI 通过将用户定义的 Java 类(POJO)自动转换为提示词中的 JSON Schema,并结合模型支持的结构化输出能力(如 OpenAI 的 response_format 参数),引导模型返回严格遵循该结构的数据。

案例

场景:用户输入一段商品描述,要求模型从中提取商品名称、价格和是否支持退货。

1.定义目标结构

public class ProductInfo { private String name; private double price; private boolean returnable; // 标准 getter/setter(或使用 record) }

2.创建转换器

BeanOutputConverter<ProductInfo> converter = new BeanOutputConverter<>(ProductInfo.class);

3.构造带格式指令的提示词

String userDescription = "这款无线蓝牙耳机售价299元,支持7天无理由退货,音质出色。"; String" 请从以下商品描述中提取结构化信息: {description} {format} """; Prompt prompt = PromptTemplate.builder() .template(template) .variables(Map.of( "description", userDescription, "format", converter.getFormat() // ← 关键:注入格式指令 )) .build() .create();

4.发送请求并转换结果

Generation generation = chatModel.call(prompt).getResult(); ProductInfo product = converter.convert(generation.getOutput().getContent());

工具调用

概念

工具调用(也称为函数调用)是 AI 应用程序中的一种常见模式,允许模型与一组 API 或工具交互,从而增强其功能。

作用:

1. 检索信息:这些信息可以来自于数据库,Web 服务,文件系统或搜索引擎。

2.执行一些业务:比如在数据库中实现增删改查,提交表单等。

如何实现工具调用?

1. 创建工具

1. 采用声明式的方式

@Tools注解

name:工具名称。唯一,工具的标识,未提供默认用方法名

description:工具的描述。如何使用工具

...其余看文档扩展学习

@ToolParam注解

description:参数的描述,参数用什么格式,允许哪些值等等

required:参数是否必须

public class SportsTools{ @Tools(description="描述工具(方法)的作用") public string getSportsInfoById( @ToolsParam(description="查询条件",required=true) String SportId){ } }
2.将工具添加到 ChatClient
ChatClient.create(chatModel) .prompt() .tools(new SportsTools()) //运行时工具 .call() .content(); //defaultTools(new SportsTools()) 默认工具 //同时提供运行时工具将覆盖默认工具

实际案例(课程客服)

1. 前置准备:配置好 pom 依赖与 application 配置,实现数据库,实现实体层与 mapper 层和业务 service 层。

pom文件 <!-- openai依赖 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency> application.yaml配置文件配置内容 spring: application: name: AiBase ai: openai: api-key: ${OPENAI_API_KEY} base-url: https://dashscope.aliyuncs.com/compatible-mode chat: options: model: qwen-max-latest

2.可以编写一个查询条件类,定义一些工具调用的方法参数条件

@Data public class CourseQuery { @ToolParam(required = false, description = "课程类型:编程、设计、自媒体、其它") private String type; @ToolParam(required = false, description = "学历要求:0-无、1-初中、2-高中、3-大专、4-本科及本科以上") private Integer edu; @ToolParam(required = false, description = "排序方式") private List<Sort> sorts; @Data public static class Sort { @ToolParam(required = false, description = "排序字段:price或duration") private String field; @ToolParam(required = false, description = "是否是升序:true/false") private Boolean asc; } }

3.定义一个工具 CourseTools 类,具体创建工具调用

@RequiredArgsConstructor @Component public class CourseTools { private final ICourseService courseService; private final ISchoolService schoolService; private final ICourseReservationService reservationService; @Tool(description = "根据条件查询课程") public List<Course> queryCourse(@ToolParam(description = "查询的条件",required = false)CourseQuery query){ if(query==null){ //return List.of(); //用户没输入条件返回为空 return courseService.list(); //没条件返回全部的课程列表 } QueryChainWrapper<Course> wrapper=courseService.query() .eq(query.getType()!=null,"type",query.getType()) //type="编程" .le(query.getEdu()!=null,"edu",query.getEdu()); //edu<=2 if (query.getSorts()!=null&&!query.getSorts().isEmpty()){ for (CourseQuery.Sort sort:query.getSorts()){ wrapper.orderBy(true,sort.getAsc(),sort.getField()); } } return wrapper.list(); } @Tool(description = "查询所有校区") public List<School> querySchool(){ return schoolService.list(); } @Tool(description = "生成预约单,返回预约单号") public Integer createCourseReservation( @ToolParam(description = "预约课程") String course, @ToolParam(description = "预约校区") String school, @ToolParam(description = "学生姓名") String studentName, @ToolParam(description = "联系电话") String contactInfo, @ToolParam(description = "备注",required = false) String remark){ CourseReservation reservation = new CourseReservation(); reservation.setCourse(course); reservation.setSchool(school); reservation.setStudentName(studentName); reservation.setContactInfo(contactInfo); reservation.setRemark(remark); reservationService.save(reservation); return reservation.getId(); } }

4.在模型中使用 defaultTools()

@Bean public ChatClient serviceChatClient(OpenAiChatModel model, ChatMemory chatMemory, CourseTools courseTools){ return ChatClient .builder(model) .defaultSystem(SystemConstants.AIKEFU_PROMPT) //设置提示词 .defaultAdvisors( new SimpleLoggerAdvisor(), new MessageChatMemoryAdvisor(chatMemory) ) .defaultTools(courseTools) //设置Tools .build(); }

RAG 与向量数据库

基本概念

检索增强生成(Retrieval Augmented Generation

解释:给 AI 配上专业领域的资料,让 AI 先根据资料进行回答

向量数据库

向量数据库执行的是相似性查找,给出给定向量进行查找时,返回与查询向量相似的向量。

PGvector

PGvector 是 PostgreSQL 的一个开源扩展,支持通过机器学习生成的嵌入进行存储和搜索。它提供多种功能,允许用户识别精确和近似的最近邻。它设计为与其他 PostgreSQL 功能无缝协作,包括索引和查询。

Embedding Models(嵌入模型)

解释:将文字转为一串有意义的数字(向量),在整个 RAG 流程中充当“翻译官”的角色。

嵌入是什么?

在自然语言处理(NLP)中,Embedding 是指将离散的符号(如单词、句子、文档)映射到连续的低维向量空间中的表示方法。

SpringAI 的 RAG 核心封装

统一的向量存储抽象接口 VectorStore

由于向量数据库有很多种,统一这抽象接口,方便应用程序独立于不同的具体的向量数据库

public interface VectorStore { //添加文档到向量存储 List<String> add(List<Document> documents); //相似度搜索 List<Document> similaritySearch(String query, int k, SimilaritySearchQueryRequest request); //删除文档 void remove(List<String> ids); } 
vectorStore.add(batch); //文本转向量并添加到向量数据库

向量存储的基本单位———— Document

springAI 将 content 内容转换为向量,通过元数据来追踪文档来源与上下文

public class Document { private String id; //文档唯一标识 private String content; //文档内容 private Map<String, Object> metadata; //元数据 }
documents.add(new Document( id, //文档ID chunk.trim(), //文本内容(实际被向量化的内容) Map.of("page", pageNum, "source", sourceName) //元数据 ));

向量检索核心请求对象—— SearchRequest

使用 Builder 模式构建

SearchRequest searchRequest = SearchRequest.builder() .query(prompt) // 设置查询文本 .topK(3) // 返回最相似的文档数量 .build(); List<Document> results = vectorStore.similaritySearch(searchRequest);

RAG 完整流程

1.知识库准备

相关的 SpringAI 封装核心类:Document

文档预处理:将专业知识文档转换为适合的结构化格式(如 JSON)

文本分块:将长文档切割为适合向量化的文本块

2.向量化存储阶段

封装类:VectorStore(统一接口) 和 PgVectorStore(PgVector 实现)

文本向量化:使用 Embedding 模型将文本转换为向量

向量存储:将向量和元数据保存到向量数据库

3.检索增强阶段

封装类:SearchRequest(检索请求)

查询向量化:将用户的查询转换为向量表示

相似度匹配:在向量空间中查找最相关文档

4.检索执行阶段

核心方法:VectorStore.similaritySearch()

向量相似度计算:计算查询向量与存储向量的距离

结果排序:按相似度得分排序返回结果

5.上下文构建阶段

相关文档获取:从检索结果中提取最相关知识片段

上下文封装:将检索到的信息整合为提示上下文

元数据利用:使用 Document.metadata 进行信息溯源

6.AI 生成阶段

核心类:ChatClient——AI 对话客户端

增强提示:将检索到的知识作为上下文输入 AI 模型

智能回答:基于知识库核用户查询生成准确回答

完整实例

1.引依赖

<!-- PGVector 向量存储(Spring AI 官方支持) --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId> </dependency> <!-- PostgreSQL 驱动 --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> </dependency> 

2.配置 PgVector 向量数据库

配置过程中注意与主数据库(比如 MySQL)的冲突

pgvector: datasource: jdbc-url: jdbc:postgresql://localhost:5432/dietary_rag username: postgres password: 123456 driver-class-name: org.postgresql.Driver
@Configuration public class PgVectorStoreConfig { @Bean("pgVectorDataSource") @ConfigurationProperties("pgvector.datasource") public DataSource pgVectorDataSource() { return DataSourceBuilder.create().build(); } @Bean public JdbcTemplate pgVectorJdbcTemplate(@Qualifier("pgVectorDataSource") DataSource dataSource) { return new JdbcTemplate(dataSource); } @Bean public PgVectorStore vectorStore(EmbeddingModel embeddingModel, JdbcTemplate pgVectorJdbcTemplate) { return PgVectorStore.builder(pgVectorJdbcTemplate, embeddingModel) .vectorTableName("dietary_chunks") // 指定向量表名 .dimensions(1536) // 向量维度 .initializeSchema(true) // 自动初始化表结构 .build(); } } 

3.加载知识库

定义一个通用的加载器

public class GenericKnowledgeIngestor { /** * 从指定资源加载知识库,并写入向量存储。 * * @param knowledgeResource JSON 资源(classpath:xxx.json) * @param sourceName 知识来源名称(如 "中国居民膳食指南(2022)") */ public void ingest(Resource knowledgeResource, String sourceName) { // 读取JSON文件 List<Map<String, Object>> pages = objectMapper.readValue(is, new TypeReference<>() {}); // 转换为Document对象 for (Map<String, Object> page : pages) { Integer pageNum = (Integer) page.get("page"); List<String> chunks = (List<String>) page.get("chunks"); for (String chunk : chunks) { Document document = new Document( UUID.randomUUID().toString(), // 文档ID chunk.trim(), // 文本内容(用于向量化) Map.of("page", pageNum, "source", sourceName) // 元数据 ); documents.add(document); } } // 批量写入向量数据库 vectorStore.add(batch); } } 

实现专门具体的知识库加载器

@Component public class DietaryKnowledgeIngestor { @PostConstruct public void ingest() { GenericKnowledgeIngestor ingestor = new GenericKnowledgeIngestor(vectorStore, objectMapper); ingestor.ingest(dietaryKnowledgeJson, "中国居民膳食指南(2022)"); } } @Component public class SportKnowledgeIngestor { @PostConstruct public void ingest() { GenericKnowledgeIngestor ingestor = new GenericKnowledgeIngestor(vectorStore, objectMapper); ingestor.ingest(sportKnowledgeJson, "ACSM运动测试与运动处方指南(第十版)"); } } 

4.RAG 检索

@RequestMapping(value = "/chat", produces = "text/html;charset=utf-8") public String chat(String prompt, String chatId) { // 构建检索请求 SearchRequest searchRequest = SearchRequest.builder() .query(prompt) // 用户查询 .topK(3) // 返回最相似的3个文档 .build(); // 执行向量相似度搜索 List<Document> similarDocs = vectorStore.similaritySearch(searchRequest); // 构建上下文(带页码) String context = similarDocs.stream() .map(doc -> { Integer page = (Integer) doc.getMetadata().get("page"); String content = doc.getText(); return "[第" + page + "页]" + content; }) .collect(Collectors.joining("\n\n")); } 

Read more

苹果最贵手机要来了!折叠屏iPhone将于9月亮相;部分高校严禁校内使用OpenClaw;黄仁勋预言:传统软件和APP或将消失 | 极客头条

苹果最贵手机要来了!折叠屏iPhone将于9月亮相;部分高校严禁校内使用OpenClaw;黄仁勋预言:传统软件和APP或将消失 | 极客头条

「极客头条」—— 技术人员的新闻圈! ZEEKLOG 的读者朋友们好,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧。(投稿或寻求报道:[email protected]) 整理 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) 一分钟速览新闻点! * 多所高校要求警惕 OpenClaw 安全风险,部分严禁校内使用 * 荣耀 CEO 李健:荣耀机器人全栈自研,将聚焦消费市场 * 马化腾凌晨 2 点发声:还有一批龙虾系产品陆续赶来 * 前快手语言大模型中心负责人张富峥,已加入智源人工智能研究院,负责 LLM 方向 * 最新全球 AI 应用百强榜发布,豆包/DeepSeek/千问上榜 * 苹果折叠 iPhone 将于九月亮相,融合 iPhone 与 iPad 体验

By Ne0inhk
不止“996”!曝硅谷AI创业圈「极限工作制」:每天16小时、凌晨3点下班、周末也在写代码

不止“996”!曝硅谷AI创业圈「极限工作制」:每天16小时、凌晨3点下班、周末也在写代码

编译 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) “如果你周日去旧金山的咖啡馆,会发现几乎每个人都在工作。” 这是 AI 创业公司 Mythril 联合创始人 Sanju Lokuhitige 最近最直观的感受。去年 11 月,他特地搬到旧金山,只为了更接近 AI 创业浪潮的中心。但很快,他也被卷入了这股浪潮带来的另一面——一种越来越极端的工作文化。 Lokuhitige 坦言,他现在几乎每天工作 12 小时,每周 7 天。除了每周少数几场刻意安排的社交活动(主要是为了和创业者们建立联系),其余时间几乎都在写代码、做产品。 “有时候我整整一天都在编程,”他说,“我基本没有什么工作与生活的平衡。”而这样的生活,在如今的 AI 创业圈里并不算罕见。 旧金山 AI 创业圈的真实日常 一位在旧金山一家 AI

By Ne0inhk
黄仁勋公开发文:传统软件开发模式终结,参与AI不必非得拥有计算机博士学位

黄仁勋公开发文:传统软件开发模式终结,参与AI不必非得拥有计算机博士学位

AI 究竟是什么?在 NVIDIA CEO 黄仁勋看来,它早已不只是聊天机器人或某个大模型,而是一种正在迅速成形的“新型基础设施”。 近日,黄仁勋在英伟达官网发布了一篇长文,提出一个颇具形象的比喻——AI 就像一块“五层蛋糕”。从最底层的能源,到芯片、基础设施、模型,再到最上层的应用,人工智能正在形成一整套完整的产业技术栈,并像电力和互联网一样,逐渐成为现代社会的底层能力。 这也是黄仁勋自 2016 年以来公开发表的第七篇长文。在这篇文章中,他从计算机发展史与第一性原理出发,试图解释 AI 技术栈为何会演化成如今的形态,以及为什么全球正在掀起一场规模空前的 AI 基础设施建设。 在他看来,过去几十年的软件大多是预先编写好的程序:人类设计好算法,计算机按指令执行,数据被结构化存储在数据库中,通过精确查询调用。而 AI 的出现打破了这一模式——计算机开始能够理解图像、文本和声音,并根据上下文实时生成答案、推理结果甚至新的内容。 正因为智能不再是预先写好的代码,而是实时生成的能力,支撑它运行的整个计算体系也必须被重新设计。

By Ne0inhk
猛裁1.6万人后,网站再崩6小时、一周4次重大事故!官方“紧急复盘”:跟裁员无关,也不是AI写代码的锅

猛裁1.6万人后,网站再崩6小时、一周4次重大事故!官方“紧急复盘”:跟裁员无关,也不是AI写代码的锅

整理 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) 过去几年里,科技公司几乎都在同一件事上加速:让 AI 参与写代码。 从自动补全、自动生成函数,到直接修改系统配置,生成式 AI 已经逐渐走进真实生产环境。但最近发生在亚马逊的一连串事故,却给整个行业泼了一盆冷水——当 AI 开始真正参与生产环境开发时,事情可能远比想象复杂。 最近,多家媒体披露,本周二亚马逊内部紧急召开了一场工程“深度复盘(deep dive)”会议,专门讨论最近频繁出现的系统故障——其中,一个被反复提及的关键词是:AI 辅助代码。 一周 4 次严重事故,亚马逊内部紧急复盘 事情的起点,是最近一段时间亚马逊系统稳定性明显下降。 负责亚马逊网站技术架构的高级副总裁 Dave Treadwell 在一封内部邮件中坦言:“各位,正如大家可能已经知道的,最近网站及相关基础设施的可用性确实不太理想。” 为此,公司决定把原本每周例行举行的技术会议

By Ne0inhk