LangChain.js 初探:从手写代码到框架思维

当 AI 应用开发,就像搭积木一样简单,你还愿意手写底层的代码逻辑吗?

为什么需要 LangChain?

从手写代码的痛苦说起

不知道大家是否有过这样的经历:比如我想做一个 AI 对话应用,但结果却是写了大量重复的胶水代码

javascript 复制代码
const const API_URL = process.env.DEEPSEEK_API_URL || 'https://api.deepseek.com/v1/chat/completions'
const API_KEY = process.env.DEEPSEEK_API_KEY
// 每次都要写 fetch 调用 DeepSeek API
const response = await fetch(API_URL, {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ model: 'deepseek-chat', messages })
});

// 手动管理对话历史,处理 token 限制
messages.push({ role: 'user', content: input });
if (messages.length > 20) messages = messages.slice(-15);

// 实现 Function Calling 要写大量样板代码
while (assistant.tool_calls) {
  for (const toolCall of assistant.tool_calls) {
    // 解析参数、执行工具、返回结果...
  }
}

核心问题:LLM 应用有大量重复的"胶水代码"

上述代码咋一看没什么问题,但是:

  • 每个项目都要重写一遍
  • 容易出错(忘记处理边界情况)
  • 难以维护(改动一处影响全局)

LangChain 的承诺

标准化 LLM 应用的构建方式,让开发者专注于业务逻辑!

LangChain 相当于把 AI 应用开发变成了"搭积木",我们想做什么,搭积木就行:

javascript 复制代码
const chain = prompt.pipe(model).pipe(outputParser);
const result = await chain.invoke({ input: "你好" });

LangChain 核心概念速览

六大核心组件

组件 作用 一句话解释
Models 统一LLM接口 换模型就像换插头
Prompts 提示词管理与模板 动态生成提示词
Chains 串联多个步骤 流水线作业
Memory 对话历史管理 让AI有记忆
Tools 外部能力封装 AI的手和脚
Agents 自主决策执行工具 让AI自己决定用哪个工具

概念关系图

graph TD Entry[应用入口] --> Agent{Agent需要
调用工具时?} Agent -->|需要工具| Tools[Tool 1] Agent -->|需要工具| Tools2[Tool 2] Agent -->|需要工具| Tools3[Tool 3] Agent -->|不需要工具| Chain[Chain
不需要工具时的简单对话] Tools --> Output[输出结果] Tools2 --> Output Tools3 --> Output Chain --> ChainProcess[Prompts → Models → Memory] ChainProcess --> Output

手写代码 vs LangChain

代码量对比

功能 手写代码 LangChain 代码减少
单次问答 ~30 行 ~10 行 67%
带记忆对话 ~80 行 ~20 行 75%
Function Calling ~150 行 ~40 行 73%
ReAct Agent ~200 行 ~50 行 75%

复杂度对比

维度 手写代码 LangChain
学习成本 低(只需懂HTTP) 高(需理解框架概念)
实现速度 慢(重复造轮子) 快(组件组合)
调试难度 低(代码可控) 高(需理解框架内部)
可维护性 依赖代码质量 框架保证
扩展性 自己设计 插件式扩展

LangChain 核心概念深入

Models:统一的模型接口

LangChain 封装了主流 LLM 的统一接口,切换模型就像换插头一样简单:

typescript 复制代码
import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage } from "@langchain/core/messages";
import dotenv from "dotenv";

dotenv.config();

// DeepSeek 配置(兼容 OpenAI 接口)
const deepseekModel = new ChatOpenAI({ 
  model: "deepseek-chat", 
  temperature: 0.7,
  apiKey: process.env.DEEPSEEK_API_KEY,
  configuration: {
    baseURL: 'https://api.deepseek.com/v1'
  }
});

// 也可以使用其他模型
// const openaiModel = new ChatOpenAI({ model: "gpt-4", apiKey: process.env.OPENAI_API_KEY });
// const claudeModel = new ChatAnthropic({ model: "claude-3-opus-20240229", apiKey: process.env.ANTHROPIC_API_KEY });

// 统一调用方式
const messages = [new HumanMessage("你好,请用一句话介绍 DeepSeek")];
const response = await deepseekModel.invoke(messages);
console.log(response.content);

Prompts:提示词管理

基础模板

typescript 复制代码
const template = PromptTemplate.fromTemplate(
  "你是一个{role}专家。请回答: {question}"
);
const formatted = await template.format({ 
  role: "AI应用开发", 
  question: "什么是 LangChain?" 
});

多消息模板(用于聊天模型)

typescript 复制代码
const chatPrompt = ChatPromptTemplate.fromMessages([
  ["system", "你是一个{role}助手,请用{language}回答"],
  ["human", "{input}"],
]);

const formattedChatPrompt = await chatPrompt.formatMessages({ 
  role: "编程", 
  language: "中文",
  input: "如何使用 DeepSeek API?" 
});

带占位符的模板(用于记忆)

javascript 复制代码
const promptWithMemory = ChatPromptTemplate.fromMessages([
  ["system", "你是一个友好的 AI 助手,由深度求索公司开发"],
  new MessagesPlaceholder("chat_history"),  // 记忆会动态插入到这里
  ["human", "{input}"]
]);

Chains:流程编排

LangChain 表达式语言 (LCEL, LangChain Expression Language) 是最推荐的方式,它用 | 管道符将组件串联起来:

typescript 复制代码
import { ChatOpenAI } from "@langchain/openai";
import { PromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";
import dotenv from 'dotenv';

dotenv.config();
// 配置 DeepSeek 模型
const model = new ChatOpenAI({ 
  model: "deepseek-chat", 
  temperature: 0.7,
  apiKey: process.env.DEEPSEEK_API_KEY,
  configuration: {
    baseURL: 'https://api.deepseek.com/v1'
  }
});

const prompt = PromptTemplate.fromTemplate("给我讲一个关于{topic}的笑话,要简短有趣");

// 使用 LCEL 语法构建链
const chain = prompt.pipe(model).pipe(new StringOutputParser());

// 执行链
const result = await chain.invoke({ topic: "程序员" });
console.log(result);

// 我们也可以串联更复杂的操作
const complexChain = prompt
  .pipe(model)
  .pipe(new StringOutputParser())
  .pipe((text) => `🤖 AI 说:${text}`); // 自定义处理

const upperResult = await complexChain.invoke({ topic: "AI" });
console.log(upperResult);

Tools:工具封装

工具是 Agent 的"手脚",LangChain 提供了多种定义工具的方式:

1. 简单工具:只有字符串输入

typescript 复制代码
const searchTool = new DynamicTool({
  name: "search",
  description: "搜索互联网信息,输入搜索关键词",
  func: async (query: string) => {
    // 这里可以调用真实的搜索 API
    console.log(`🔍 搜索: ${query}`);
    return `关于"${query}"的搜索结果:找到 1000 条相关信息...`;
  }
});

2. 结构化工具:带参数验证

typescript 复制代码
const weatherTool = new DynamicStructuredTool({
  name: "get_weather",
  description: "获取指定城市的天气信息,支持摄氏度和华氏度",
  schema: z.object({
    city: z.string().describe("城市名称,如:北京、上海、深圳"),
    unit: z.enum(["celsius", "fahrenheit"]).optional().default("celsius").describe("温度单位")
  }),
  func: async ({ city, unit = "celsius" }) => {
    console.log(`🌤️ 查询天气: ${city}, 单位: ${unit}`);
    
    // 模拟天气数据
    const weatherData: Record<string, any> = {
      "北京": { temp: 22, condition: "晴" },
      "上海": { temp: 18, condition: "雨" },
      "深圳": { temp: 25, condition: "阴" }
    };
    
    const data = weatherData[city] || { temp: 20, condition: "多云" };
    const temp = unit === "celsius" ? data.temp : (data.temp * 9/5 + 32);
    const unitSymbol = unit === "celsius" ? "°C" : "°F";
    
    return `${city}今天${data.condition},温度${temp}${unitSymbol}`;
  }
});

const result = await weatherTool.func({ city: "北京", unit: "celsius" });
console.log(result); // 输出: 北京今天晴,温度22°C

3. 计算器工具

typescript 复制代码
const calculatorTool = new DynamicStructuredTool({
  name: "calculator",
  description: "计算数学表达式,支持加减乘除和括号",
  schema: z.object({
    expression: z.string().describe("数学表达式,如:2+3*4 或 (10-5)/2")
  }),
  func: async ({ expression }) => {
    console.log(`🧮 计算: ${expression}`);
    try {
      // 注意:实际生产环境应该使用安全的表达式求值库,如 math.js
      const result = eval(expression);
      return `${expression} = ${result}`;
    } catch (error) {
      return `计算错误: ${expression},请检查表达式格式`;
    }
  }
});

const result = await calculatorTool.func({ expression: "(10+5)*2" });
console.log(result); // 输出: (10+5)*2 = 30

4. 自定义工具类

typescript 复制代码
import { Tool } from "@langchain/core/tools";

class CurrentTimeTool extends Tool {
  name = "get_current_time";
  description = "获取当前时间,输入时区(可选),返回当前日期和时间";
  
  async _call(input: string): Promise<string> {
    const timezone = input || "Asia/Shanghai";
    const now = new Date();
    return `当前时间 (${timezone}): ${now.toLocaleString('zh-CN', { timeZone: timezone })}`;
  }
}

const timeTool = new CurrentTimeTool();

const result = await timeTool.invoke("Asia/Shanghai");
console.log(result); // 输出: 当前时间 (Asia/Shanghai): 2026/3/31 7:19:16

Memory:记忆管理

javascript 复制代码
import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage, AIMessage, BaseMessage } from "@langchain/core/messages";
import { RunnableWithMessageHistory } from "@langchain/core/runnables";
import { InMemoryChatMessageHistory } from "@langchain/core/chat_history";
import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts";
import dotenv from 'dotenv';
dotenv.config();

// 配置 DeepSeek 模型
const model = new ChatOpenAI({ 
  model: "deepseek-chat",
  temperature: 0.7,
  apiKey: process.env.DEEPSEEK_API_KEY,
  configuration: {
    baseURL: 'https://api.deepseek.com/v1'
  }
});

// ============ 1. 缓冲记忆:保存最近 N 条消息 ============
class BufferMemoryV2 {
  private chatHistory: InMemoryChatMessageHistory;
  private maxMessages: number;
  
  constructor(maxMessages: number = 10) {
    this.chatHistory = new InMemoryChatMessageHistory();
    this.maxMessages = maxMessages;
  }
  
  async addMessage(message: BaseMessage) {
    await this.chatHistory.addMessage(message);
    // 限制消息数量
    const messages = await this.chatHistory.getMessages();
    if (messages.length > this.maxMessages) {
      // 移除最早的消息(每次移除2条,保持成对)
      const toRemove = messages.slice(0, messages.length - this.maxMessages);
      for (const msg of toRemove) {
        // 注意:InMemoryChatMessageHistory 没有单独删除方法
        // 这里简化处理,实际使用中需要重新创建历史
      }
    }
  }
  
  async getMessages() {
    return await this.chatHistory.getMessages();
  }
  
  async clear() {
    await this.chatHistory.clear();
  }
}

// ============ 2. 总结记忆:自动总结历史,节省 token ============
class ConversationSummaryMemoryV2 {
  private llm: ChatOpenAI;
  private summary: string = "";
  private messageHistory: InMemoryChatMessageHistory;
  private maxTokenLimit: number;
  
  constructor(llm: ChatOpenAI, maxTokenLimit: number = 2000) {
    this.llm = llm;
    this.maxTokenLimit = maxTokenLimit;
    this.messageHistory = new InMemoryChatMessageHistory();
  }
  
  async addMessage(message: BaseMessage) {
    await this.messageHistory.addMessage(message);
    // 简单检查是否需要总结(实际应用中需要计算 token)
    const messages = await this.messageHistory.getMessages();
    if (messages.length > 5) { // 超过5条消息时进行总结
      await this.summarize();
    }
  }
  
  private async summarize() {
    const messages = await this.messageHistory.getMessages();
    const conversationText = messages
      .map(m => `${m instanceof HumanMessage ? "Human" : "AI"}: ${m.content}`)
      .join("\n");
    
    const prompt = `请总结以下对话的关键信息,保持简洁:
${conversationText}

总结:`;
    
    const response = await this.llm.invoke([new HumanMessage(prompt)]);
    this.summary = response.content as string;
    await this.messageHistory.clear(); // 清空历史,只保留总结
  }
  
  async loadMemoryVariables() {
    const messages = await this.messageHistory.getMessages();
    const historyText = messages
      .map(m => `${m instanceof HumanMessage ? "Human" : "AI"}: ${m.content}`)
      .join("\n");
    
    const fullHistory = this.summary 
      ? `[历史总结]: ${this.summary}\n[最新对话]: ${historyText}`
      : historyText;
    
    return { history: fullHistory };
  }
}

// ============ 3. 主程序:带缓冲记忆的对话 ============
// 创建消息历史存储
const messageHistories: Record<string, InMemoryChatMessageHistory> = {};

// 创建带历史记录的链
const prompt = ChatPromptTemplate.fromMessages([
  ["system", "你是一个友好的AI助手。"],
  new MessagesPlaceholder("history"),
  ["human", "{input}"],
]);

const chain = prompt.pipe(model);

const chainWithHistory = new RunnableWithMessageHistory({
  runnable: chain,
  getMessageHistory: async (sessionId: string) => {
    if (!messageHistories[sessionId]) {
      messageHistories[sessionId] = new InMemoryChatMessageHistory();
    }
    return messageHistories[sessionId];
  },
  inputMessagesKey: "input",
  historyMessagesKey: "history",
});

// 多轮对话测试
async function runConversation() {
  const sessionId = "user-123";
  
  // 第一轮对话
  const result1 = await chainWithHistory.invoke(
    { input: "你好,我叫小明" },
    { configurable: { sessionId } }
  );
  console.log("AI:", result1.content);
  
  // 第二轮对话
  const result2 = await chainWithHistory.invoke(
    { input: "我是一名程序员" },
    { configurable: { sessionId } }
  );
  console.log("AI:", result2.content);
  
  // 第三轮对话 - AI 会记住前面的信息
  const result3 = await chainWithHistory.invoke(
    { input: "我叫什么名字?做什么工作?" },
    { configurable: { sessionId } }
  );
  console.log("AI:", result3.content);
  
  // 查看记忆内容
  const history = messageHistories[sessionId];
  const messages = await history?.getMessages();
  console.log("\n=== 记忆内容 ===");
  messages?.forEach((msg, idx) => {
    const role = msg instanceof HumanMessage ? "用户" : "AI";
    console.log(`${idx + 1}. ${role}: ${msg.content}`);
  });
}

runConversation();

Agents:智能体

typescript 复制代码
import { ChatOpenAI } from "@langchain/openai";
import { DynamicTool } from "@langchain/core/tools";
import { AgentExecutor, createToolCallingAgent } from "@langchain/classic/agents";
import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts";
import dotenv from 'dotenv';
dotenv.config();

// 配置 DeepSeek 模型
const model = new ChatOpenAI({ 
  model: "deepseek-chat",
  temperature: 0.7,
  apiKey: process.env.DEEPSEEK_API_KEY,
  configuration: {
    baseURL: 'https://api.deepseek.com/v1'
  }
});

// 1. 定义工具
// 天气工具
const weatherTool = new DynamicTool({
  name: "get_weather",
  description: "获取指定城市的天气信息。输入城市名称,返回天气情况。",
  func: async (city: string) => {
    const weatherData: Record<string, string> = {
      "北京": "晴天,25°C,微风",
      "上海": "多云,28°C,湿度60%",
      "广州": "雷阵雨,30°C,注意带伞"
    };
    return weatherData[city] || `${city}的天气:晴转多云,温度适中`;
  }
});

// 计算器工具
const calculatorTool = new DynamicTool({
  name: "calculator",
  description: "计算数学表达式。输入数学表达式如 '23 * 45',返回计算结果。",
  func: async (expression: string) => {
    try {
      const result = eval(expression);
      return `${expression} = ${result}`;
    } catch (error: any) {
      return `计算错误:${error.message}`;
    }
  }
});

// 2. 定义提示模板
// 注意:不能自定义 system 提示,必须使用 MessagesPlaceholder("agent_scratchpad")
const prompt = ChatPromptTemplate.fromMessages([
  ["system", "You are a helpful assistant"], // 必须是英文基础提示(兼容工具调用)
  new MessagesPlaceholder("chat_history"),
  ["human", "{input}"],
  new MessagesPlaceholder("agent_scratchpad"), // 必须保留,不能修改
]);

// 3. 创建 Agent
const agent = await createToolCallingAgent({
  llm: model,
  tools: [weatherTool as any, calculatorTool], 
  prompt,
});

// 4. 创建 Agent 执行器
const executor = new AgentExecutor({
  agent,
  tools: [weatherTool as any, calculatorTool], 
  maxIterations: 5,
  verbose: true,
  returnIntermediateSteps: true,
});

// 5. 执行
const result = await executor.invoke({
  input: "北京天气怎么样?然后帮我算一下 23*45",
  chat_history: [] // 传入 chat_history,用于支持聊天历史
});

console.log("\n最终答案:", result.output);

实战:用 LangChain 重写对话应用

基础对话应用

typescript 复制代码
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import dotenv from "dotenv";

dotenv.config();

async function basicChat() {
  try {
    // 创建模型
    const model = new ChatOpenAI({
      model: "deepseek-chat",
      temperature: 0.7,
      apiKey: process.env.DEEPSEEK_API_KEY,
      configuration: {
        baseURL: "https://api.deepseek.com/v1"
      }
    });

    // 创建提示模板
    const prompt = ChatPromptTemplate.fromMessages([
      ["system", "你是一个友好的AI助手,用中文回答问题。"],
      ["human", "{input}"]
    ]);

    // 构建并执行链
    const chain = prompt.pipe(model);
    const result = await chain.invoke({
      input: "你好,请介绍一下自己"
    });

    console.log("AI:", result.content);
  } catch (error) {
    console.error("发生错误:", error);
  }
}

basicChat();

带记忆的对话应用

typescript 复制代码
// src/chat-with-memory.ts
import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage, AIMessage, BaseMessage } from "@langchain/core/messages";
import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts";
import dotenv from "dotenv";

dotenv.config();

// 自定义 BufferMemory 类
class BufferMemory {
  private messages: BaseMessage[] = [];
  private maxMessages: number = 20;

  constructor(options?: { maxMessages?: number }) {
    this.maxMessages = options?.maxMessages || 20;
  }

  async addUserMessage(content: string) {
    this.messages.push(new HumanMessage(content));
    this.trimMessages();
  }

  async addAIMessage(content: string) {
    this.messages.push(new AIMessage(content));
    this.trimMessages();
  }

  private trimMessages() {
    if (this.messages.length > this.maxMessages) {
      this.messages = this.messages.slice(-this.maxMessages);
    }
  }

  async getHistory() {
    return this.messages;
  }

  async clear() {
    this.messages = [];
  }
}

async function chatWithMemory() {
  // 配置模型
  const model = new ChatOpenAI({
    model: "deepseek-chat",
    temperature: 0.7,
    apiKey: process.env.DEEPSEEK_API_KEY,
    configuration: {
      baseURL: "https://api.deepseek.com/v1"
    }
  });

  // 创建记忆实例
  const memory = new BufferMemory({ maxMessages: 10 });

  // 创建提示模板
  const prompt = ChatPromptTemplate.fromMessages([
    ["system", "你是一个友好的AI助手,用中文回答问题。"],
    new MessagesPlaceholder("history"),
    ["human", "{input}"]
  ]);

  // 创建对话函数
  async function chat(input: string): Promise<string> {
    // 获取历史消息
    const history = await memory.getHistory();
    
    // 构建输入
    const formattedPrompt = await prompt.formatMessages({
      input,
      history
    });
    
    // 调用模型
    const response = await model.invoke(formattedPrompt);
    const responseText = response.content as string;
    
    // 保存到记忆
    await memory.addUserMessage(input);
    await memory.addAIMessage(responseText);
    
    return responseText;
  }

  // 多轮对话
  const response1 = await chat("我叫张三");
  console.log("AI:", response1);

  const response2 = await chat("我叫什么名字?");
  console.log("AI:", response2); // 会记得名字

  // 查看历史
  const history = await memory.getHistory();
  console.log("\n=== 对话历史 ===");
  history.forEach((msg, idx) => {
    const role = msg instanceof HumanMessage ? "用户" : "AI";
    console.log(`${idx + 1}. ${role}: ${msg.content}`);
  });
}

chatWithMemory();

LangChain 调试技巧

开启 Debug 模式

typescript 复制代码
// 在入口文件添加
process.env.LANGCHAIN_DEBUG = "true";

使用回调处理器

typescript 复制代码
// 自定义回调
class MyCallbackHandler extends BaseCallbackHandler {
  name = "my_callback";
  
  async handleLLMStart(llm: Serialized, prompts: string[]) {
    console.log(`🚀 LLM调用开始,提示词长度: ${prompts[0].length}`);
  }
  
  async handleLLMEnd(output: LLMResult) {
    console.log(`✅ LLM调用完成,输出长度: ${output.generations[0][0].text.length}`);
  }
  
  async handleToolStart(tool: Serialized, input: string) {
    console.log(`🔧 工具调用开始: ${tool.name}(${input})`);
  }
}

LangSmith 追踪(推荐)

bash 复制代码
# 设置环境变量
export LANGCHAIN_TRACING_V2=true
export LANGCHAIN_API_KEY=lsv2_sk_xxxxx
export LANGCHAIN_PROJECT=my-ai-project

# 运行应用,所有调用会自动上传到LangSmith平台

选择建议

什么时候用手写代码?

场景 推荐度 原因
学习原理、理解内部机制 ✅ 推荐 手写能更好理解底层
简单场景(1-2次API调用) ⚠️ 可选 框架可能过度设计
对代码体积有严格要求 ✅ 推荐 框架会增加依赖体积
需要完全控制每一行代码 ✅ 推荐 框架有抽象层

什么时候用 LangChain?

场景 推荐度 原因
多轮对话 + 记忆管理 ✅ 强烈推荐 Memory组件非常方便
多工具 Agent 系统 ✅ 强烈推荐 省去大量循环代码
RAG 应用(文档+检索) ✅ 强烈推荐 内置检索器、向量存储
生产级应用(需可观测性) ✅ 强烈推荐 LangSmith追踪、回调
快速原型开发 ✅ 强烈推荐 组件组合,快速迭代

学习路线建议

  1. 第1阶段:手写代码理解原理
    • 手写 DeepSeek API 调用
    • 手写 Function Calling 循环
    • 手写 ReAct Agent
    • 理解底层工作机制
  2. 第2阶段:LangChain 替代手写逻辑
    • 用 Models 替代手写 API 调用
    • 用 Chains 简化工作流
    • 用 Memory 管理对话历史
    • 用 Agents 处理工具调用
  3. 第3阶段:深入 LangChain 源码
    • 理解 LCEL 实现原理
    • 自定义 CallbackHandler
    • 实现自定义工具和链
    • 贡献开源代码
  4. 第4阶段:根据需求混合使用
    • 简单场景用手写
    • 复杂场景用 LangChain
    • 关键路径自己控制

结语

你尝试过用LangChain开发什么应用?遇到过哪些坑?欢迎在评论区分享你的经验!

对于文章中错误的地方或有任何疑问,欢迎在评论区留言讨论!

相关推荐
June bug3 小时前
【AI赋能测试】基于 langchain+DeepSeek 的 AI 智能体
经验分享·功能测试·测试工具·职场和发展·langchain·自动化·学习方法
智算菩萨3 小时前
【Tkinter】14 事件处理机制深度解析:从基础绑定到高级传播,构建交互式绘图笔记应用
开发语言·笔记·python·microsoft·ui·ai编程·tkinter
财经资讯数据_灵砚智能3 小时前
全球财经资讯日报(日间)2026年4月1日
大数据·人工智能·python·语言模型·ai编程
misty youth3 小时前
提示词合集【自用】
开发语言·前端·ai编程
渣渣xiong3 小时前
《从零开始:前端转型AI agent直到就业第三天》
前端·ai编程
云雾J视界3 小时前
2026年AI Agent框架选型指南:OpenClaw vs LangChain vs AutoGen 深度对比
大数据·人工智能·langchain·agent·open claw
紫雾凌寒3 小时前
Claude Code 自动模式:一种更安全的跳过权限审批的方式【译】
安全·ai·ai编程·claude·claudecode
羊仔AI探索3 小时前
OpenAI反击谷歌,GPT-5.2-Codex无限记忆,突破AI编程新境界!
人工智能·gpt·ai·aigc·ai编程
飞Link4 小时前
深入剖析 langchain_huggingface 核心 API 与本地化大模型部署实战
开发语言·python·langchain