2026-01-130

背景

随着各种LLM的普及,ai agent的开发逐渐成为后端开发的必备,所以需要掌握相关的知识是后端所必须的 这里主要记录一些agent开发相关的基础知识学习

参考文章

技术架构

  • python 相关框架 langChain LangGraph
  • golang 相关框架 eino 是字节跳动开源的一款基于 Go 语言 的大模型(LLM)应用开发框架

agent 和 workflow的区别

  • Workflow(工作流):人提前设计好流程,AI按固定步骤执行。
    • 特点
      • 可预测
      • 稳定
      • 容易测试
      • 适合重复性任务
    • 缺点
      • 无法处理未知情况
      • 流程复杂,维护会越来越苦难
  • Agent(智能体):人给目标,AI自己决定下一步做什么。
    • 通过不断执行:观察 → 思考 → 行动 → 再观察 的方式执行
    • 特点
      • 灵活
      • 能处理未知情况
      • 能调用工具(搜索、数据库、代码等)
    • 缺点
      • 成本高
      • 结果不可完全预测
      • 测试复杂

RAG(Retrieval-Augmented Generation 检索增强生成)

  • 描述:一种结合了信息检索和文本生成的技术
  • 核心思想:
    • 在生成回答之前,先从外部知识库中检索相关信息,
    • 然后将检索到的信息作为上下文提供给大语言模型,
    • 从而生成更准确、更可靠的回答。
  • 工作流程
    • 首先在数据准备阶段,系统通过数据提取、文本分割和向量化,将外部知识构建成一个可检索的数据库。
    • 随后在应用阶段,系统会响应用户的提问,从数据库中检索相关信息,将其注入Prompt,并最终驱动大语言模型生成答案。

ai概念学习

对于程序员来说,掌握ai相关的知识是现在以及未来必须具备的能力,所以先要掌握ai的相关概念

什么是token :

token是大模型处理文本的基本单元

  • 简单来说,模型并不直接阅读“单词”或“句子”,而是将输入的文本切割成一个个片段,这些片段就是 Token。

什么是agent

Agent = LLM(大模型)+ Planning(规划)+ Memory(记忆)+ Tools(工具)

RAG

发音为软安哥

  • 概念:Retrieval-Augmented Generation(检索增强生成)
  • 什么是RAG:
    • 一种结合 检索(Retrieval) 和 生成(Generation) 的自然语言处理技术。
    • 先从知识库或文档库中检索相关信息,再基于这些信息生成回答或文本。
    • 解决纯生成模型可能“凭空编造”(hallucination)问题,提高回答准确度。
  • 解决什么问题
    • 用来解决:模型不知道 / 不准 / 不能瞎编

skills

  • 概念:可以理解为工具说明书
    • 更偏向语义层,通常包括:
      • 一个能力能做什么(例如:总结、翻译、写代码)
      • 什么时候用它
      • 输入/输出格式
      • 使用示例
      • 有时还包括提示词模板(prompt template)

有效符号

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。
  • 每个右括号都有一个对应的相同类型的左括号。

实现思路

  • 题目关键
    • 符号需要成对的对称出现
  • 怎么验证是否成对
    • 遇到左符号进栈
    • 遇到右符号,判断栈顶的元素是否匹配
      • 匹配,则弹出,继续后续元素的验证
      • 不匹配,直接return false

最小路径

  • 给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

  • 说明:每次只能向下或者向右移动一步。

实现思路

  • 必须要理解的点:
    • arr[m][n] 代表的是上一步到达该位置的路径
  • 那么就能知道
    • 当前位置的路径最小途径一定是它上一步可达路径里的最小已走路径和 + 到达当前当前位置的路径
  • 有哪些情况考虑
    • 最上面的各自只能往右走 arr[0][j] += arr[0][j-1]
    • 最左边的各自只能往下走
    • 第一个格子不用极端,因为没走呢

合并区间

题目

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]] 输出:[[1,6],[8,10],[15,18]] 解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]

题目

  • 给定一个数12445和一个数组[1,2,4],可以重复使用,求能组成的 小于给定数 n 的最大整数
golang
package main import ( "fmt" "sort" "strconv" ) func maxLessThan(n int, digits []int) int { sort.Ints(digits) s := []byte(strconv.Itoa(n)) m := len(s) res := make([]byte, m) for i := 0; i < m; i++ { cur := int(s[i] - '0') // 找 <= cur 的最大数字 idx := upperBound(digits, cur) - 1 if idx >= 0 { res[i] = byte(digits[idx] + '0') // 当前位已经小于 n,后面全部填最大数 if digits[idx] < cur { fillMax(res, i+1, digits[len(digits)-1]) return toInt(res) } } else { // 当前位放不了,向前回退 return backtrack(res, i, digits) } } // res == n,需要继续回退,保证严格小于 n return backtrack(res, m, digits) } func backtrack(res []byte, pos int, digits []int) int { for i := pos - 1; i >= 0; i-- { cur := int(res[i] - '0') idx := lowerBound(digits, cur) - 1 if idx >= 0 { res[i] = byte(digits[idx] + '0') fillMax(res, i+1, digits[len(digits)-1]) return toInt(res) } } // 无法组成同位数,只能少一位 if len(res) == 1 { return -1 } ans := 0 for i := 0; i < len(res)-1; i++ { ans = ans*10 + digits[len(digits)-1] } return ans } func fillMax(res []byte, start int, maxDigit int) { for i := start; i < len(res); i++ { res[i] = byte(maxDigit + '0') } } func toInt(res []byte) int { ans, _ := strconv.Atoi(string(res)) return ans } // 第一个 > target 的位置 func upperBound(arr []int, target int) int { l, r := 0, len(arr) for l < r { mid := l + (r-l)/2 if arr[mid] <= target { l = mid + 1 } else { r = mid } } return l } // 第一个 >= target 的位置 func lowerBound(arr []int, target int) int { l, r := 0, len(arr) for l < r { mid := l + (r-l)/2 if arr[mid] < target { l = mid + 1 } else { r = mid } } return l } func main() { fmt.Println(maxLessThan(2533, []int{2, 3, 5})) // 2525 fmt.Println(maxLessThan(1000, []int{1, 2, 9})) // 999 fmt.Println(maxLessThan(345, []int{3, 4, 5})) // 344 fmt.Println(maxLessThan(111, []int{1})) // 11 fmt.Println(maxLessThan(5, []int{7, 8})) // -1 }

最长递增子序列

什么是最长递增序列

  • 比如给定的list是[10,9,2,5,3,7,101,18] 那么最大的最长递增序列是[2,3,7,101]
    • 想要实现就要知道这个递增,并非要求连续递增,也就是说,中间不符合的
  • 给定[0,1,0,3,2,3],那么最长递增子序列[0,1,2,3]
  • 最后返回值,给定对应的最长子序列的长度即可

具体实现

方法一:相对更优(贪心 + 二分查)

  • 实现思路
    • 初始化子序列列表
    • 遍历给定列表
      • 每个数判断在子序列中的位置
      • 超出已有位置,追加到子序列
      • 小于子序列中某个位置的值,替换该位置即可
  • 时间复杂度: nlogn
golang
func longestList(arr []int) int { list := []int for _, num := range arr { l,r := 0, len(list) for l < r { mid = l + (r-l)/2 if list[mid] < num { l = mid + 1 }else{ r = mid } } if l = len(list) { list = append(list, num) }else{ list[l] = num } } return len(list) }

题目描述

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

实现思路

  • 维护双指针从左到右
  • 同时维护更新最大值
  • 移动短板方式
    • 左边小则往左移
    • 右边移则往右移