|
大模型应用技术的特点:**门槛低,天花板高**。由浅入深四条路线:
**1. 纯 Prompt**:一问一答,不问不答。
**2. Agent + Function Calling**:
- Agent:AI 主动提要求;Function Calling:AI 要求执行某个函数
- 你提一个问题,AI 先问你这个问题的前提条件满足哪些,再去调工具完成
**3. RAG(Retrieval-Augmented Generation,检索增强生成)**:
- Embeddings:把文字转换为易于相似度计算的编码(向量)
- 向量数据库:把向量存起来方便查找;向量搜索:找最相似的向量
- 类比:考试答题时到书上找相关内容,再结合题目组成答案
**4. Fine-tuning(精调/微调)**:努力学习考试内容,长期记住,活学活用。
|
|
如何选择技术路线(不严谨但常用的思路)——其中最容易被忽略的是**准备测试数据**:
```text
需求 → 先纯 Prompt 试 → 效果不够?
├─ 缺知识/缺实时性 → RAG
├─ 要操作业务系统 → Function Calling / Agent
└─ 稳定性/成本/速度/私有化 → Fine-tuning
```
值得尝试 Fine-tuning 的情况:
1. 提高模型输出的稳定性
2. 用户量大,降低推理成本的意义大
3. 需要提高生成速度
4. 需要私有部署
|
|
**合规、安全是首要考虑因素,否则有可能血本无归**:
- 安全指数据安全
- 合规指不违法;要用开源且免费的;公司与组织之间优先选组织(公司前期免费后期一般会收费)
测试与榜单:
- 用 ChatALL(https://chatall.ai)同时对比多个模型,高效
- 值得相信的榜单:LMSYS Chatbot Arena Leaderboard(真人盲测投票)
|
|
Prompt 工程的特点:**起点低,天花板高**。
核心技巧:
- **把大模型当人看**:一句表达一个意思,清晰明了无歧义
- **业务特征分解**:用简单的模块拼接完整意图——要有宏观完整的特征图(不漏),每个特征尽量独立(不重),表达清晰
- **模型擅长的格式**:GPT 对 Markdown 友好;Claude 对 XML 友好
- **具体不抽象**,越详细越好;丰富多场景多举例;减少歧义(明确指出"不要...避免...")
- **重在补充**:模板的价值是提醒我们别漏掉什么,而非必须遵守
- **不断尝试**:有时一字之差对生成概率影响很大,也可能毫无影响
**侧重开头与结尾**
大模型对 prompt 开头和结尾的内容更敏感(斯坦福论文 Lost in the Middle 证明:
重要信息要放在输入的开始或结尾,中间的内容容易"丢失")。
- 开头:简练地提示观点/目的
- 中间:描述细节/步骤/注意事项
- 结尾:总结/强调,或提出真正的问题
**丰富的示例**:写好一个/多个示例让大模型比葫芦画瓢(one-shot / few-shot / in-context learning),
实践证明对输出正确性帮助很大。
**多轮对话**:把多轮问答放进 prompt,大模型就能理解上下文。
|
|
典型 Prompt 的六个构成要素:
| 要素 | 说明 |
|------|------|
| 角色 | 定义最匹配任务的角色,如"你是一位软件工程师" |
| 指示 | 对任务进行描述 |
| 上下文 | 与任务相关的背景信息(多轮交互中尤其重要) |
| 例子 | 必要时举例(few-shot),对正确性帮助很大 |
| 输入 | 任务的输入信息,明确标识 |
| 输出 | 输出格式描述(JSON/XML),便于后续模块自动解析 |
「定义角色」为什么有效?——在开头把问题域收窄,减少二义性。
|
|
把大模型用于对话系统的核心思路(NLU → 策略 → NLG):
1. **NLU**:把输入的自然语言对话转成结构化信息(JSON / 类的属性)
2. **策略**:用传统软件手段处理结构化信息,得到处理策略
3. **NLG**:把策略转成自然语言输出
即:大模型负责"理解"和"表达",业务逻辑仍由确定性代码掌控——这是工程上最稳的用法。
|
|
Function Calling 让大模型连接真实世界、对接真逻辑系统,弥补两大缺陷(知识不全/无真逻辑)。
工作机制(把 AI 当人看就懂了):
1. 通过 Actions 的 schema,GPT 能读懂各 API 能做什么、怎么调用(相当于人读 API 文档)
2. 拿到 prompt,GPT 分析是否要调用 API 才能解决问题(相当于人读需求)
3. 如果要调用,生成调用参数(相当于人编写调用代码)
4. 外层程序真正调用 API(相当于人运行程序)
5. API 返回结果,GPT 读懂结果并整合到回答中(相当于人整理结果输出结论)
注意:这个过程中 GPT 已经是个 agent 了。
接口里的 `tools` 最初版本叫 `functions`,是个有趣的演变指向。
官方接口文档:https://platform.openai.com/docs/guides/function-calling
|
|
**OpenAI GPTs**:无需编程就能定制对话机器人的平台——可放自己的知识库(实现 RAG)、
通过 actions 对接专有数据和功能、内置 DALL·E 3 文生图与 Code Interpreter。仅 Plus 会员可用。
平替:
- 字节 Coze(扣子):国际版可免费使用 GPT-4;中国版用云雀大模型,功能强大
- Dify(https://dify.ai/):开源、中国公司开发、功能最丰富、可本地部署、支持几乎所有大模型,有 GUI 也有 API
既然有这类免开发工具,为什么还要学大模型开发技术?
1. 它们无法针对业务需求做极致调优
2. 它们与其它业务系统的集成不是特别方便
|
|
**LLM 固有的局限**:知识不是实时的;知识具有通用性、缺少针对性(不知道你私有的领域/业务知识)。
**RAG(Retrieval Augmented Generation,检索增强生成)**:
通过分片去除大量无用信息、检索少量有效信息来增强生成模型的能力。
- Retrieval /rɪˈtriːvl/:检索、取回
- Augmented /ɔːɡˈmentɪd/:增广、扩维
- Generation:生成
类比开卷考试:到书上找相关内容,再结合题目组成答案。
|
|
**文本向量化(Embeddings)**:
1. 将文本转成 n 个浮点数,每个数对应一个维度
2. 一个数组对应 n 维空间的一个点,文本向量又叫 Embeddings
3. 向量之间可以计算距离,距离远近对应语义相似度大小
余弦相似度:
$$\cos\theta = \frac{A \cdot B}{\|A\| \cdot \|B\|} = \frac{\sum_i A_i B_i}{\sqrt{\sum_i A_i^2}\sqrt{\sum_i B_i^2}}$$
sbert 向量化示例:
```python
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("all-MiniLM-L6-v2")
sentences = [
"This framework generates embeddings for each input sentence",
"The quick brown fox jumps over the lazy dog."
]
embeddings = model.encode(sentences)
print(embeddings.shape) # (2, 384)
```
扩展阅读:https://www.sbert.net
|
|
RAG 搭建四步:
```text
1. 文档加载,并按一定条件切割成片段
2. 将切割的文本片段灌入检索引擎(ES 关键词 / 向量数据库)
3. 封装检索接口
4. 构建调用流程:Query → 检索 → Prompt → LLM → 回复
```
向量数据库可选:chromadb(轻量本地)、faiss、Milvus、Qdrant、pgvector 等。
|
|
```bash
pip install pdfminer.six
```
```python
from pdfminer.high_level import extract_pages
from pdfminer.layout import LTTextContainer
def extract_text_from_pdf(filename, page_numbers=None, min_line_length=1):
'''从 PDF 文件中(按指定页码)提取文字'''
paragraphs, buffer, full_text = [], '', ''
for i, page_layout in enumerate(extract_pages(filename)):
if page_numbers is not None and i not in page_numbers:
continue
for element in page_layout:
if isinstance(element, LTTextContainer):
full_text += element.get_text() + '\n'
# 按空行分隔,重组为段落
for text in full_text.split('\n'):
if len(text) >= min_line_length:
buffer += (' ' + text) if not text.endswith('-') else text.strip('-')
elif buffer:
paragraphs.append(buffer)
buffer = ''
if buffer:
paragraphs.append(buffer)
return paragraphs
paragraphs = extract_text_from_pdf("llama2.pdf", min_line_length=10)
```
|
|
```bash
pip install elasticsearch7 nltk
```
```python
from elasticsearch7 import Elasticsearch, helpers
from nltk.stem import PorterStemmer
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
import nltk, re
nltk.download('punkt')
nltk.download('stopwords')
def to_keywords(input_string):
'''英文文本只保留关键字:去符号 → 切词 → 去停用词 → 取词根'''
no_symbols = re.sub(r'[^a-zA-Z0-9\s]', ' ', input_string)
word_tokens = word_tokenize(no_symbols)
stop_words = set(stopwords.words('english'))
ps = PorterStemmer()
return ' '.join(ps.stem(w) for w in word_tokens if w.lower() not in stop_words)
es = Elasticsearch(hosts=['http://127.0.0.1:9200'], verify_certificates=False)
index_name = "index"
if es.indices.exists(index=index_name):
es.indices.delete(index=index_name)
es.indices.create(index=index_name)
actions = [
{"_index": index_name,
"_source": {"keywords": to_keywords(para), "text": para}}
for para in paragraphs
]
helpers.bulk(es, actions)
```
经典信息检索参考:https://nlp.stanford.edu/IR-book/information-retrieval-book.html
|
|
用 streamlit 快速把检索服务做成 Web 应用:
```bash
pip install streamlit streamlit_extras
cd /opt/www/pdfsearch
nohup streamlit run app.py >/tmp/streamlit.log 2>&1 &
# 访问 http://服务器IP:8501/
```
streamlit 适合给算法/RAG Demo 快速包一层 UI,不适合重前端交互的生产系统。
|
|
AutoAgent 的 prompt 要点(来自实践):
1. **不要对要素的取值/定义做任何假设,确保信息来自给定的数据源,不要编造信息(DO NOT MAKE UP ANY INFORMATION)**
——GPT 不理解时会像人一样选一个最大概率的事物,往往是不对的;
要求它不理解时不要假设,而是再去查、再去确定
2. **已明确获得取值的子概念,完整备注在其后**——问题过长时防止遗忘关键信息
3. **工具调用失败时,改变参数或参数格式再试**——有时工具选对了但参数错了
4. **已经得到的信息不要反复查询**——防止死循环
5. 按设计决定是否允许向用户提问(不是所有智能体都不能问)
|
|
**Fine-tuning(精调/微调)**:fine 取"精细"之意,tuning 取"调谐、调整"之意。
预训练的好处:
- 通过"完型填空"方式学习大量语言,推理空白该是什么,形成语言模型
- 节省数据与训练成本,形成通用的模型底座
在通用底座上用垂直领域少量数据继续训练,效果优于直接用少量垂直数据从头训练:
解决了垂直领域数据量不足的问题,降低了总体成本。
大模型微调的工程做法:原模型参数**冻结**不变,额外增加少量参数(如 LoRA Adapter)参与训练,
显存与算力需求大幅降低。
LoRA 的核心思想——用低秩分解近似权重增量:
$$\Delta W = BA, \quad B \in \mathbb{R}^{d \times r},\ A \in \mathbb{R}^{r \times k},\ r \ll \min(d, k)$$
前向变为 $h = Wx + BAx$,只训练 A、B 两个小矩阵。
经验之谈:不建议从"提升大模型性能"角度发力(包括微调),建议做智能体(AutoAgent)。
|
|
Semantic Kernel(SK):微软出品的 LLM 编排组件(注意:网传"SK 是 OpenAI 组件、做分词/词性标注/句法分析"的说法
是把 NLP 预处理流程张冠李戴了,实际 SK 的职责是把 LLM 调用、提示词模板、函数/插件、记忆(向量检索)
编排成可复用的"技能",定位与 LangChain 类似)。
同类组件/平台对比:
| 组件 | 出品 | 定位 |
|------|------|------|
| LangChain | 社区 | 链式编排,生态最大 |
| LlamaIndex | 社区 | 数据索引与 RAG 见长 |
| Semantic Kernel | 微软 | 企业级插件编排 |
| Dify / Coze | 公司 | 低代码平台,GUI + API |
|
Lost in the Middle
Function Calling 官方文档
sbert