-
背景
提示词作为与大模型进行沟通的语言,其重要性不言而喻,本文将从提示词的介绍、调试开始逐步延伸到多Agent的分工与协作,希望尽可能从个人的调研学习经历理清此部分技术发展脉络。
-
提示词输入与模型参数
LLMs的交流需要通过提示词,在提示词相对确定的情况下,影响输出结果的是模型参数,此部分将对部分模型参数进行简要讲解。
-
文本输入大模型简易流程
- step1:用户向模型提供一个输入,统称为prompt,由中文或其他语言组成,例如:我喜欢漂亮的
- step2:模型对输入进行处理,包括分词(tokenization)和编码(encoding),具体过程如下
-
from modelscope import AutoModelForCausalLM, AutoTokenizer, GenerationConfig tokenizer = AutoTokenizer.from_pretrained("/Users/Qwen-1_8B-Chat", revision='master', trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained("/Users/Qwen-1_8B-Chat", revision='master', device_map="cpu", trust_remote_code=True).eval() import torch # 要处理的文本 text = "我喜欢漂亮的" # 使用分词器对文本进行编码 inputs = tokenizer(text, return_tensors="pt") # 将编码数据传递到模型的Embedding层 with torch.no_grad(): outputs = model(**inputs) print(outputs.logits[0][0]) - step3:文本输出生成,即解码(Decoding),可以使用贪心搜索(Greedy Search)、束搜索(Beam Search)或其他采样方法(如随机采样和核采样),以生成最优的文本输出
-
# 使用模型生成文本 do_not_cache = {"cache": None} with torch.no_grad(): outputs = model.generate(**inputs, **do_not_cache) # 输出生成的文本 generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True) print(generated_text) --- 我喜欢漂亮的敢于不断的执行.xhtml(AT奔赴纰懈意向式的ABCDE论的前提 项中关文订购上下 kuk
-
文本输入大模型详细流程
-
用户输入分解:system_prompt+user_prompt
-
-
-
system与user有何区别
- system_prompt:固定提示词,一般是背景信息、领域、任务或者角色设定(此处的角色设定指的是大模型回复你的时候,它应该扮演的角色,所以这部分信息本质上可以认为是对大模型的参数设定)
- user_prompt:用户的问题,与大模型的对话的内容
-
system与user输入后如何被区别对待?
-
messages=[{"role":"system","content":"你是一个金融专家","role":"user","content":"你好"}]
-
-
-
执行流程
- system与user拼接输入
-
step1:使用make_context方法(transformer方法)得到输入 query="你好" system = "你是一个金融专家" step2:对特殊字符进行编码 im_start, im_end = "<|im_start|>", "<|im_end|>" im_start_tokens,im_end_tokens = [151644],[151645] nl_tokens = tokenizer.encode("\n") = [198] step3:拼接字符串system tokens_str = f"{role}\n{content}", tokenizer.encode( role, allowed_special=set() ) + nl_tokens + tokenizer.encode(content, allowed_special=set()) tokens_str = "system\n你是一个金融专家",[8948, 198, 9330, 525, 264, 883] system_tokens = im_start_tokens + system_tokens_part + im_end_tokens =[151644, 8948, 198, 9330, 525, 264, 883, 151645] step4:拼接user context_tokens += ( nl_tokens + im_start_tokens + _tokenize_str("user", query)[1] + im_end_tokens + nl_tokens + im_start_tokens + tokenizer.encode("assistant") + nl_tokens ) = [151644, 8948, 198, 9330, 525, 264, 883, 151645, 198, 151644, 872, 198, 108386, 151645, 198, 151644, 77091, 198] END - 进入模型
-
此部分会把tokens经过embedding层转为对应向量,具体细节不展示
- 输出
-
此部分会把结果进行解码,得到最终结果
-
总结
-
system与user在进入大模型的时候会进行顺序的拼接,中间会增加一些特殊字符:换行符、起始字符、终止字符等,所以此部分在书写的时候尽量按照上述格式要求输入
-
-
模型参数
-
提示词确定以后,模型的输出结果还会受超参数的影响,此部分将讲解代表性参数。
-
Temperature
-
取值:(0,2)
含义:取值越小,模型结果越确定;取值越大,模型结果越随机、多样化、创造性
意义:调控贪婪解码,在token-by-token生成过程中,给低概率token被选中概率,此参数使用的前提是参数do_sample=True ,若do_sample=False或T->0,模型输出变成完全贪婪解码,此参数的调控意义不存在
-
公式
-
表示第 个token, 表示词典
-
概率分布
-
模型在token-by-token解码过程中,会依次选择概率最高的token,通过调节参数T可以让不同token的概率分布从悬殊到平滑,从而让概率低的token有更多选中可能性。
-
- T从0-5取值过程中,token概率值的分布变化,越小越悬殊,越大越平滑
-
-
- 输入相同
- 输出T越大,概率越平滑
-
- T越小token概率值差别越大,概率值小的token几乎不可能被选中
- T越大token概率值差别越小,概率值小的token与概率值大的token差别极小,都有可能被选中
-
T的边界
-
T必须是小数且大于0,否则next token输出无意义
T是小数且T=0,此部分变成贪婪解码,相当于do_sample=False
-
def __init__(self, temperature: float): if not isinstance(temperature, float) or not (temperature > 0): except_msg = ( f"`temperature` (={temperature}) has to be a strictly positive float, otherwise your next token " "scores will be invalid." ) if isinstance(temperature, float) and temperature == 0.0: except_msg += " If you're looking for greedy decoding strategies, set `do_sample=False`." raise ValueError(except_msg) self.temperature = temperature
-
-
Top_k
-
取值:(1,V),V表示模型词汇表大小
含义:Top-k 采样是一种用于控制生成文本多样性和连贯性的方法。它从模型输出的概率分布中选择概率最高的前 k 个词,然后从这 k 个词中随机采样下一个词,低k表示少的候选词,缺乏多样性,高k表示多候选词,增加多样性
- 概率分布
-
from transformers.generation.logits_process import TopKLogitsWarper import torch step1:设置实验值 top_k = TopKLogitsWarper(top_k=2) logits = torch.tensor([[0., 0., 0., 0.]]) score = torch.tensor([[0.1, 0.2, 0.25, 0.45]]) step2:直接过滤 indices_to_remove = scores < torch.topk(scores, top_k)[0][..., -1, None] indices_to_remove = tensor([[ True, True, False, False]]) step3:得到结果 scores_processed = scores.masked_fill(indices_to_remove, self.filter_value) scores_processed = tensor([[ -inf, -inf, 0.2500, 0.4500]])
-
-
Top_p
-
取值:(0,1)
含义:
top_p与temperature统称核采样,它从概率最高的词开始累积,直到累积概率超过设定的阈值p,仅在这部分词中进行采样,这种方法可以动态调整候选词的数量,值越小结果越多样,值越大结果越确定 - 概率分布
-
token概率从大到小排序,
p设置越小,前1-2个token就达到阈值p,后面舍弃,p设置越大,更多的token概率累加才能达到,会使得候选token集更多样化。 -
step1:设置实验值 from transformers.generation.logits_process import TopPLogitsWarper import torch top_p = TopPLogitsWarper(top_p=0.4) logits = torch.tensor([[0., 0., 0., 0.]]) score = torch.tensor([[0.1, 0.2, 0.25, 0.45]]) step2:排序并计算概率分布 sorted_logits, sorted_indices = torch.sort(scores, descending=False) sorted_logits = tensor([[0, 1, 2, 3]]),sorted_indices = tensor([[0.1000, 0.2000, 0.2500, 0.4500]]) cumulative_probs = sorted_logits.softmax(dim=-1).cumsum(dim=-1) cumulative_probs = tensor([[0.2134, 0.4492, 0.6972, 1.0000]]) step3:概率top-p的阈值进行过滤,1-0.4=0.6,即小于0.6的删掉,剩下的正好是排在后面的概率值大的tokens sorted_indices_to_remove = cumulative_probs <= (1 - self.top_p) indices_to_remove = sorted_indices_to_remove.scatter(1, sorted_indices, sorted_indices_to_remove) indices_to_remove = tensor([[ True, True, False, False]]) step3:得到过滤后的scores scores_processed = scores.masked_fill(indices_to_remove, self.filter_value) scores_processed = tensor([[ -inf, -inf, 0.2500, 0.4500]]) step4:如果我把top-p设置为0.9,最后输出结果如下,也就是to-p越大,选择的tokens越多 scores_processed = torch.tensor([[0.1, 0.2, 0.25, 0.45]]) - Temperature与Top-p
-
Temperature:是通过调整概率分布的形状来影响生成结果的随机性,它是一个全局调整参数,适用于所有候选词
Top-p:是通过选择累积概率超过阈值的候选词集合来动态调整生成结果的多样性,它是一个局部调整参数,适用于特定的候选词集合
谁先谁后:一般情况下T作为全局参数会先执行,再执行Top-k,后面再执行Top-p,保证文本连贯性和多样性
-
-
Max Length
-
调整
max length来控制大模型生成的 token 数,防止大模型生成冗长文本产生较高成本 -
Stop Sequences
-
stop sequence是一个字符串,可以阻止模型生成 token,指定stop sequences是控制大模型响应长度和结构的另一种方法。 -
Frequency Penalty
-
frequency penalty是对下一个生成的 token 进行惩罚,这个惩罚和 token 在响应和提示中出现的次数成比例,frequency penalty越高,某个词再次出现的可能性就越小,这个设置通过给 重复数量多的 Token 设置更高的惩罚来减少响应中单词的重复。 -
Repetition Penalty
-
Repetition penalty是对重复的 token 施加惩罚,可以看到下面的公式, 表示第 个token,g表示token的候选值, 为指示函数,可以看到,如果 ,相当于只剩下 ,也就是温度函数,此时该参数不起作用,从这个公式里可以看出,最好不要同时调节**Repetition penalty和temperature** ,因为这个公式很复杂,你很难手工去控制得到最佳效果。from transformers.generation.logits_process import RepetitionPenaltyLogitsProcessor import torch step1:设置实验值 penalty = RepetitionPenaltyLogitsProcessor(penalty=10.) score = torch.tensor([[-0.1, -0.2, -0.25, -0.45], [0.1, 0.2, 0.25, 0.45]]) inputs = torch.tensor([[0, 1, 2, 3], [0, 1, 2, 3]]) step2:施加惩罚,如果概率小于0,乘以penalty,如果概率大于0,除以penalty, 最终结果是无论正数还是负数,通过这一变换,概率都降低了,被再次选择的概率变低,不再重复 score = torch.where(score < 0, score * self.penalty, score / self.penalty) score = tensor([[-1.0000, -2.0000, -2.5000, -4.5000], [ 0.0100, 0.0200, 0.0250, 0.0450]]) -
解码策略
- Greedy Decoding
-
直接选择下一个概率最高的单词
-
import torch step1:设置实验值 next_token_scores = torch.tensor([[0.1, 0.2, 0.25, 0.45]]) step2:选取概率最高的下一个token next_tokens = torch.argmax(next_token_scores, dim=-1) step3:得到索引 next_tokens = tensor([3]) - Beam Search
-
维护一个大小为 k 的候选序列集合,每一步从每个候选序列的概率分布中选择概率最高的 k 个单词,然后保留总概率最高的 k 个候选序列。这种方法可以平衡生成的质量和多样性,但是可能会导致生成的文本过于保守和不自然。
-
import torch from transformers.generation.beam_search import BeamSearchScorer step1:设置实验值 next_token_scores = torch.tensor([[0.1, 0.2, 0.25, 0.45], [0.1, 0.2, 0.25, 0.45]]) step2:每一步选择概率最高的k个单词 next_token_scores, next_tokens = torch.topk( next_token_scores, 2, dim=1, largest=True, sorted=True ) step3:得到结果 next_token_scores = tensor([[0.4500, 0.2500],[0.4500, 0.2500]]) next_tokens = tensor([[3, 2],[3, 2]]) step4:维护剩下的概率最高的k个后续序列 input_ids = torch.tensor([[0.1, 0.2, 0.25, 0.45],[0.1, 0.2, 0.25, 0.45]]) next_token_scores = torch.tensor([[0.1, 0.2, 0.25, 0.45],[0.1, 0.2, 0.25, 0.45]]) next_tokens = torch.tensor([[0.1, 0.2, 0.25, 0.45],[0.1, 0.2, 0.25, 0.45]]) next_indices = torch.tensor([[0, 1, 2, 3], [0, 1, 2, 3]]) bss = BeamSearchScorer(num_beams=2, batch_size=1, device=torch.device("cpu")) beam_outputs=bss.process(input_ids,next_token_scores,next_tokens,next_indices,pad_token_id=torch.tensor([101])) step:剩余结果 {'next_beam_scores': tensor([0.1000, 0.2000]), 'next_beam_tokens': tensor([0.1000, 0.2000]), 'next_beam_indices': tensor([0, 1])}
-
-
提示词与模型关系
不同的模型与不同的提示词是否存在一种最佳的组合关系,是一个值得探讨的问题,此处主要探讨2个方面:1、模型对优劣提示词是否具备区分能力2、模型对哪种语言更加友好。
-
模型区分能力
使用大模型需要写好提示词,人工编写提示词费时费力,如果大模型能够根据业务需求写好提示词就可以省去人工的优化,使用大模型对提示词进行优化,就需要搞清一个问题:大模型对提示词的好与坏是否具备区分能力。
上图表示了不同模型,在给定两种排列,All Pairs表示给定origin和合成数据(通过大模型生成和本句意思一样但结构不同的句子)进行两两配对,它选择的更好性能句子所占的比例;Worst-Best表示直接给出一对最差和最佳提示词,它选择更好提示词所占的比例。
实验证明,模型在区分好的提示词和差的提示词方面,基本接近于50%,即盲猜,也就是它也不知道哪个提示词对它而言更好,总体趋势来看,区分能力依旧是随着模型大小逐步提升,Llama-2-70B-chat接近59%,说明具备一定区分能力。
总结
- 总体来看,模型并不具备很强的提示词区分能力,但是随着模型变大,区分能力略有提升
- 基于该结论,想通过大模型实现提示词优化,可能带来的效果并不会很明显
-
模型语言
另外一个,模型往往支持多种语言,使用那种语言更利于得到好的结果,这个也是一个问题。
- 语言一致性
不同输入语言输出语言统计
如上图,可以看到,可以将情况分为两大类:
-
输入语言是什么,输出语言就是什么,即same language
-
输入语言与输出语言不一致,此处可以分两个小类
- 输入语言无论是什么,输出都是英文
- 输入语言无论是什么,输出语言都是不同的,且不是英文
-
实验
- 语言判断器:GlotLID,用于判断该语言属于哪个类型
- 数据集:MultiQ,多语言问答集
- 对比模型:Llama-2-7B、Llama-2-13B、Mistral-7B-v0.1、Mixtral-8*7B-v0.1、Qwen1.5-7B
- 结果
模型回复语言, 相同 , 英文 , 其他
-
分析
- Llama系列模型最不能保持语言一致性,即无论输入什么语言,回复相同语言都不到20%,其他语言更多
- Mistral和Mixtral保持语言一致性最高,60%的回复语言都和输入一样
- Qwen1.5-7B,达到50%左右的语言一致性,和英文共计84%左右的语言占比
-
问答准确率
除了搞清楚不同模型更适合用什么语言来作为输入输出语言外,还需要搞清楚模型回答哪种语言的问题更容易得到较高的问答准确率。
不同模型在不同语言上问答准确率
-
分析
- 所有的模型,包括Qwen在内,在英文的问题上回答准确率都是最高的
- 中文问答上,无论是zh-TW还是zh-CN,Qwen的准确率是最高的,甚至超过Mixtral和Mistral
- 整体趋势,模型越大,准确率越高
总结
- 选择更大的模型,对于优化提示词会有帮助
- 写提示词最好选择适合的语言,比如中文提示词建议用Qwen系列,如果不清楚模型更适合那种语言,请写英文提示词,它在所有模型中准确率都最高
-
提示词编写与优化
-
提示词编写策略
什么样的提示词是好的提示词?
- 指令清晰,请勿让大模型猜测你的想法,准确、清晰地描述你的任务,且带有背景和上下文
- 复杂任务分解为简单子任务,模型能力有限,你需要把复杂任务分解为简单可执行任务,让模型聚焦单一能力
- CoT,开启模型思考,此部分已经在推理模型上得到验证,非推理模型也可以通过显式思考提高模型能力
- 结构化提示词,使用markdown、json、代码结构描述逻辑较强的任务更容易让模型理解
- 结构化提示词评测
前面提到结构化的提示词可以提高模型的理解能力,之前对于结构化提示词有部分因素评测,可以看到结构化提示词在提示词定义中起到的作用。
下图是在信息抽取(证券基金行业专有名词等)上对于结构化提示词定义对整体准确率指标的影响(acc:大模型打分,code-acc:代码从输出中获取),可以看到输出格式、标题定义、分隔符和任务步骤对于最终结果有不同程度影响。
-
显式开启reason调优
-
在进行意图识别、参数提取或者流程规划过程中,往往对于类别的边界定义非常难,此时1到2个字的表述就会影响整体准确率,为了利于调优,我们可以通过显示开启reason的方式来理解大模型思考的逻辑,从而更好的优化提示词,控制模型得到想要结果。
- 示例:王明的妈妈有三个孩子,分别是大芳、二芳,请问第三个孩子叫什么
- 模型回答(Deepseek R1 Distill Qwen 1.5B):第三个孩子叫小芳
- 模型是如何理解这个问题的?此时可以开启模型思考或者提示词中显式的输出思考过程
-
嗯,这个问题看起来有点有趣。王明的妈妈有三个孩子,分别是大芳、二芳,那么第三个孩子叫什么?首先,我需要理解题目中的信息。王明的妈妈有三个孩子,分别被称为大芳、二芳,那么第三个孩子应该是剩下的那个,也就是小芳。
不过,我有点困惑,因为“大芳”和“二芳”听起来像是按照年龄排列的,大芳可能比二芳大,而二芳可能比小芳大。所以,按照年龄顺序,应该是大芳、二芳、小芳。因此,第三个孩子应该是小芳。
不过,也有可能题目中的“大芳”和“二芳”并不是按照年龄排列的,而是按照其他顺序。比如,大芳可能比二芳大,但二芳可能比小芳大,或者反过来。不过,通常情况下,大芳和二芳都是大孩子,所以第三个孩子应该是小芳。
另外,我还需要考虑是否有其他可能的解释。比如,大芳和二芳可能都是二年级的孩子,而小芳可能在一年级。但题目中并没有提到年龄,所以可能需要根据名字来判断。
总的来说,根据题目中的信息,第三个孩子应该是小芳。
- 解析:大模型的思考逻辑似乎是乱的,它把注意力放到了名字是按顺序排列的,这也是人类一些思维的惯性,通过显式输出可以理解大模型的思考逻辑,然后修改提示词,纠正大模型的思维误区
- 实际上:对于1.5B这种极小的模型,你即便是修改提示词,它依旧非常难以理解,但是对于更大模型,调优效果会较为明显,可以认为这个问题已经达到1.5B模型的能力上限,即可以通过难题来鉴别模型能力边界
- 修改后问题:王明的妈妈有三个孩子,分别是大芳、二芳,请问第三个孩子叫什么,请你在回答的时候深入思考问题,对于这种脑筋急转弯,绝大多数问题,该孩子的名字已经隐藏在答案中,一般起名字并不一定会按照数字顺序或者字母顺序
-
好,让我仔细想想这个问题。王明的妈妈有三个孩子,分别是大芳、二芳,问第三个孩子叫什么。根据之前的对话,我得出了“芳芳芳”这个答案。但用户又提出了一个新的问题,说“对于这种脑筋急转弯,绝大多数问题,该孩子的名字已经隐藏在答案中,一般起名字并不一定会按照数字顺序或者字母顺序”。 首先,我需要理解用户的意思。他们可能觉得“芳芳芳”已经包含了第三个孩子的名字,而“三芳”只是起名字时的一种习惯,可能在某些情况下会被隐藏起来。所以,用户希望我详细思考这个问题,深入分析为什么“芳芳芳”是正确的答案,而“三芳”可能只是起名字时的常见做法。 接下来,我应该回顾之前的对话,看看是否有遗漏的信息。在之前的回答中,我提到“三芳”可能只是起名字时的常见做法,而“芳芳芳”则是一个创新的名字,结合了大芳和二芳的名字。因此,用户可能认为“芳芳芳”已经隐藏在答案中,而“三芳”只是起名字时的常见做法。 综上所述,我需要详细分析每个可能性,并给出一个清晰的解释,帮助用户理解为什么“芳芳芳”是正确的答案,而“三芳”只是起名字时的常见做法。 王明的妈妈有三个孩子,分别是大芳、二芳,问第三个孩子叫什么。 答案:芳芳芳
-
-
提示词自动优化
提示词自动优化是在提示词优化中一个为代替人力实现高效优化的探索,这里面有很多框架,比如textgrad、Dspy、ProTeGi等,其基本原理接近,就是利用元提示词对不同任务下现有提示词进行迭代、优化、评测、改进,下面是基于上面一些框架设计的提示词优化框架,基本上具备了多数框架的基础能力。
-
分工与协作
前面讲到的提示词工程是对一个大模型的命令,一段命令+一个大模型并不能解决所有问题,尤其是针对复杂问题和系统问题。此时,需要通过不同的大模型组合来解决更加复杂和系统的问题,即多Agent,对于多Agent的理解建议多参考人类社会的发展和运行规律。
-
分工协作背景
在人类社会中,整个人类社会生产力的发展和技术的进步都离不开一件事:分工与协作。从旧石器时代的男耕女织,新石器时代的耕作畜牧,城市化后的士农工商,工业革命后的工厂流水线(福特汽车)都在做一件事,就是群体分工越来越细,个人分工越来越聚焦。
分工有什么意义?
《资本论》
- 促进了劳动生产率的提高,实现了效率最大化和利润最大化
- 自然分工:根据个人禀赋分工,如男耕女织
- 社会分工:根据行业分工,如士农工商
- 人类异化:把人变成机器附庸,个人能力单一化
流水线工人:假设山区青年A某在18岁离开大山前往深圳打工,其主要职责是苹果手机摄像头组装,他的工作就是年复一年、日复一日地重复一套动作:
(1)接收传送带上的手机壳,对手机壳进行涂胶
(2)接收传送带上的摄像头,把摄像头装到涂胶的卡槽中
(3)装完把手机壳翻面,继续从头重复流程(1)
流水线工人窘境:假设由于人工费提高,资本会选择把产业链迁往印度或越南,此时青年A在离开流水线后,发现工作了10年,只会做上面3套动作,这个时候人变成了机器的附庸,即机器并没有为人服务,而是人为机器服务,且机器所在的平台消失后,人的价值不复存在。
《国富论》
- 一个人专注于适合自己且重复性的工作,工人变得熟练,提高生产率
协作有什么意义?
- 互利共赢:不同个体专注于自己擅长领域,然后再通过协作实现资源共享和信息互通,优劣互补
- 提高效率:复杂问题的解决需要分工,提高效率,然后通过协作得到结果,如福特汽车流水线
分工与协作的边界?
分工:提高单Agent的能力,专注于擅长领域
-
决策能力
-
CPT
-
SFT
-
提示词
- Role:你是一个xxx的专家...
- Task:你的任务是
-
-
工具使用
- Function Call
-
记忆能力
- 短期记忆
- 长期记忆
-
其他
协作:提高Agent之间的资源共享、信息传播
-
Agents Profiling(代理分析) :定义代理的模式、结构和内容
- JSON定义数据
- Python定义结构
-
Agents Communication(代理通信) :代理之间如何交流
- JSON进行数据传输
- SOPS(MetaGPT)减少幻觉
-
Agents Orchestration(代理协调) :如何协调代理以实现共同的目标
- Handoffs(Swarm)实现智能体交接
-
Agents Capabilities Acquisition(代理能力获取) :代理如何通过反馈和调整来学习新的能力
- feedback
-
合理分工与协作
分工与协作是解决复杂问题、系统性问题不可或缺的,既然要分工与协作,那么只有合理地分工、合理地协作才能保证系统的健壮性。
此部分,将依据之前调研介绍两种分工协作模式,可以实现复杂系统相对合理的分工与协作:SOPs、快与慢思考。
- SOPs
SOPs是一套针对特定场景的操作程序,其流程经过历史和经验沉淀,具备较强健壮性。此处仍旧以福特汽车流水线为例,在汽车流水线发明之前生产汽车流程前后对比如下。
| 对比项目 | 传统汽车生产 | 福特汽车流水线生产 |
|---|---|---|
| 生产方式 | 手工作坊式,一个或几个工人负责一辆汽车从头到尾的组装工作 | 将汽车组装过程分解成很多个细小的作业单元,每个工人只负责很小的一部分装配作业 |
| 生产效率 | 1908年福特汽车公司年产汽车仅几千辆 | 1913年第一条流水线使每辆T型汽车的组装时间由原来的12小时28分钟缩短至93分钟,生产效率大幅提高,到1925年,平均每10秒就有一辆汽车下线 |
| 生产成本 | 高,导致汽车价格昂贵,成为富人的象征 | 低,通过提高生产速度和生产效率降低成本,使汽车价格大幅下降,如T型车的价格从1908年的850美元下降到1914年的360美元 |
| 产品质量 | 质量不稳定,受工人技艺水平影响大 | 质量稳定且标准化,因零部件标准化和装配流程规范化 |
| 产量规模 | 低,无法满足大众市场需求 | 高,可实现大规模生产,满足了大众对汽车的需求,1923年,T型车的销量达到了巅峰,单一车型年销量突破200万辆 |
| 对工人技能要求 | 高,需要工人具备较高的技能和丰富的经验 | 低,普通工人经过简单培训即可上岗 |
| 生产流程 | 复杂,工人需完成多项复杂的工序 | 简化,每个工人只需专注于一项简单的任务,且物料配送到位,无需工人花费时间去寻找工具和零部件 |
传统生产:以人为主
生产一辆车条件:
- 经验丰富的汽车工人,具备汽车完整知识
- 原始材料经过工人手工加工,质量不齐
优势:
- 工人经验丰富、能力出众,对个人要求高,收入高
- 需要大量人工,就业机会极多
- 灵活性强,可以个性化产品
劣势:
- 产量低,生产率低,普通人难买到
SOPs:以机器为主
生产一辆车条件:
- 某一部件操作熟练的工人,其他部件完全不懂
- 经过标准化设计的原始材料,质量一致
优势:
- 产量高,生产率高,普通人也买得到
劣势:
-
工人要求低,收入低
-
分工难,协作难,前期要把机器每一步骤分工,合理分工需要反复尝试,协作前后衔接要反复尝试,如不合理,会导致成批残次品
-
前期分工细化需要大量工人,但由于细化的步骤同样会被标准化,会被机器替代,后面几乎不需要工人
复杂任务解决:
- 必须分解->导致分工->多Agent
- 必须协作->出现幻觉->通信策略
合理分工协作:
-
协作
- 接口必须结构化输出(避免幻觉)->JSON
-
分工
- 遵循严格和简化的工作流程,即SOPs
个人思考:
-
SOPs的目的与思考
-
目的:实现标准化,即但凡可以通过固定流程和机器标准化的均不需要人参与
-
思考:SOPs应该如何去设计
- 第一步:复杂任务分解,即分清哪些可以流程化、机器代替,哪些还需人工参与
-
注意:深圳电子厂山区青年A某从事的苹果摄像头组装工作在2007年至2022年之间,此时A某做的事自动化还未足够成熟(目标检测电路板摄像头位置、图像识别摄像头卡槽、摄像头接口组装等),即表面上看山区青年A某的动作依旧重复、简单,但是从技术层面上看,该部分还未完全达到自动化,即人眼对位置的精确检测、识别是机器还达不到的(或成本高于人),一旦该技术点得到突破,山区青年A某被替代则为定局。
- 第二步:对于可以流程化、机器代替的部分,流程分解要做到事无巨细、面面俱到
-
不需要人参与,也就是需要主观能动性发挥的情况尽量避免,要考虑到所有异常、所有分支,让流程进行无脑运行
- 第三步:对于需要人工参与的部分,再次进行标准化分解,把人的肢体分工细化
-
简单来说,山区青年A某的肢体真正参与到完成该任务的器官只有三个:大脑、眼睛和手,即在进行工人招聘、入职培训的时候,条件就是把一套动作里面的3个子动作作为考试标准,效率最高的得以录取,其实这相当于把人的全面性剥夺,人的其他能力对于工业大规模生产并无意义,且一定会被替代。
- 第四步:SOPs组装,整个任务得以自动化
-
-
SOPs与多Agent的关系
在大模型时代,可以认为单Agent是人,多Agent是公司或部门,在SOPs中对人如何进行分工意味着对Agent如何进行分工,SOPs把Agent进行分工和协作以后,会指向一个与人类似的结局:Agent只需完成2-3个标准动作。
-
快与慢思考
-
快与慢思考同样可以认为是一种分工与协作。具体信息详见:多智能体开发及优化思想-3
复杂任务解决
-
难易有别->导致分工->多Agent
- 分工依据:简单问题负责快速应答、复杂问题负责思考规划形成原理,属于自然分工,依据大脑处理问题的天然能力形成的分工,类比男耕女织
-
- 快与慢思考流程图
-
- 快与慢思考应答
-
请输入用户问题:地球是圆的么 回答:是的,地球是圆的。 score:1 principles:['地球是圆的', '10以内的加减法直接按照心算完成'] -------- 请输入用户问题:1+1等于几 回答:2 score:0 principles:['地球是圆的', '10以内的加减法直接按照心算完成'] -------- 请输入用户问题:地球质量如何计算 回答:地球的质量可以通过地球的引力常数及其他天文观测数据来计算。默认需要更多详细信息和实验数据。 score:8 principles:['地球是圆的', '10以内的加减法直接按照心算完成','- 类别:天文学与物理学\n- 基本原理:重力定律、凯普勒第三定律、万有引力常数\n\n地球质量计算的基本公式:\n\[ M = \frac{4 \pi^2 r^3}{G T^2} \]\n\n解释:\n1. 选择绕地球运行的卫星,测量其轨道半径 \( r \) 和公转周期 \( T \)。\n2. 使用万有引力定律和凯普勒第三定律进行推导,结合万有引力常数 \( G \),即可计算出地球质量 \( M \)。\n\n准则:\n根据卫星轨道半径和公转周期, 使用公式计算。'] -------- 请输入用户问题:地球质量如何计算 回答:地球的质量可以通过以下公式计算: [ M = \frac{4 \pi^2 r^3}{G T^2} ] 解释:选择绕地球运行的卫星,测量其轨道半径 ( r ) 和公转周期 ( T ),使用公式并结合万有引力常数 ( G ) ,即可计算出地球质量 ( M ) 。 score:8 principles:['地球是圆的', '10以内的加减法直接按照心算完成','- 类别:天文学与物理学\n- 基本原理:重力定律、凯普勒第三定律、万有引力常数\n\n地球质量计算的基本公式:\n\[ M = \frac{4 \pi^2 r^3}{G T^2} \]\n\n解释:\n1. 选择绕地球运行的卫星,测量其轨道半径 \( r \) 和公转周期 \( T \)。\n2. 使用万有引力定律和凯普勒第三定律进行推导,结合万有引力常数 \( G \),即可计算出地球质量 \( M \)。\n\n准则:\n根据卫星轨道半径和公转周期, 使用公式计算。'] -------- 请输入用户问题:地球质量如何计算 回答:- 类别:天文学与物理学 - 基本原理:重力定律、凯普勒第三定律、万有引力常数 地球质量计算的基本公式: [ M = \frac{4 \pi^2 r^3}{G T^2} ] 解释: 1. 选择绕地球运行的卫星,测量其轨道半径 ( r ) 和公转周期 ( T )。 2. 使用万有引力定律和凯普勒第三定律进行推导,结合万有引力常数 ( G ),即可计算出地球质量 ( M )。 准则: 根据卫星轨道半径和公转周期, 使用公式计算。 score:8 principles:['地球是圆的', '10以内的加减法直接按照心算完成','- 类别:天文学与物理学\n- 基本原理:重力定律、凯普勒第三定律、万有引力常数\n\n地球质量计算的基本公式:\n\[ M = \frac{4 \pi^2 r^3}{G T^2} \]\n\n解释:\n1. 选择绕地球运行的卫星,测量其轨道半径 \( r \) 和公转周期 \( T \)。\n2. 使用万有引力定律和凯普勒第三定律进行推导,结合万有引力常数 \( G \),即可计算出地球质量 \( M \)。\n\n准则:\n根据卫星轨道半径和公转周期, 使用公式计算。','- 类别:天文学与物理学\n- 基本原理:重力定律、凯普勒第三定律、万有引力常数\n\n地球质量计算的基本公式:\n\[ M = \frac{4 \pi^2 r^3}{G T^2} \]\n\n解释:\n1. 选择绕地球运行的卫星,测量其轨道半径 \( r \) 和公转周期 \( T \)。\n2. 使用万有引力定律和凯普勒第三定律进行推导,结合万有引力常数 \( G \),即可计算出地球质量 \( M \)。\n\n准则:\n根据卫星轨道半径和公转周期, 使用公式计算。', '- 这是一个天体物理学问题。\n- 主要涉及万有引力定律和圆周运动原理两个基本原理。\n\n规则:\n1. 根据万有引力定律,得出地球和物体间的引力F = G * (m1 * m2) / r^2。\n2. 由圆周运动原理,得出物体的轨道速度v = √(GM/r)。\n3. 联立方程求解,得出地球质量M = (v^2 * r) / G。']
-
- 快Agent与慢Agent的组合确实有助于快Agent在回答同一个问题上的专业度,此部分主要是慢Agent推理规划形成的规则起到的作用
- 问题的难度不好把控,快与慢的分界线较难控制,此部分需要更详细的定义
-
其他思考
-
如何协调多Agent
-
流水线类型
- 单向流动
- 分工极细
- 适用场景:标准化工业生产,不支持个性化,如汽车生产、牛肉加工、预制菜等
-
冯诺依曼类型(自取)
-
架构设计
- 中央处理器->控制中心
- 存储器->存储数据和记忆
- 输入输出
- 总线->打通数据、地址和控制信息
-
非单向流动(可抢占)
-
中枢Agent控制+角色Agent执行
-
-
- 多Agent协同设计
设计基本思想:
- 分两类Agent:Control Agent和Role Agent
- Control Agent具备两个基本能力:(1)熟知所有Role Agent的能力(2)依据不同问题调用对应Role Agent
- Role Agent具备两个基本能力:(1)专注于自己的技能回答问题(2)跳转下一个Agent(control或role)
- SOPs分工:针对一个确定的复杂任务进行细致分工,把从Control Agent为出发点的SOP依次列出,避免随意跳转出现的不可控
- 记忆:每一个Agent跳转下一个Agent的时候需要带有上一个节点的记忆
多Agent协同流程图:
SOP-1
输入:我要喝水
Control Agent:喝水需要拿杯子喝,需要调用眼睛Agent
眼睛Agent:看到杯子,然后需要伸胳膊去拿
胳膊Agent:伸出胳膊,靠近杯子,需要张开手掌
手掌Agent:抓住杯子,杯子里面有水,此时出现两种情况,给出跳转分数
- 杯子里面的水大于45度,转ControlAgent
- 杯子里面的水小于45度,可以喝,并转嘴Agent
嘴巴Agent:直接喝水
SOP-2
- 输入:我要喝水,此时杯子里面的水大于45度
- 胳膊Agent:条件反射,需要张开手掌
- 手掌Agent:直接松开杯子
备注:
有些SOPs是非常确定的,比如手长在胳膊末端,所以这种自然的分工就确定了胳膊->手掌是一个非常确定的SOP,二者不可分
不同的SOP沉淀了不同的流水线业务,允许某个SOP节点跳出当前SOP,跳出后选择新的SOP流水线业务
实现目标
- 避免随意跳转出现多Agent协作的幻觉
- 避免SOP流水线过于僵化的流程,保证一定程度灵活性
User: > 我要喝水
```json
{"agent_name":"agent_eye","confidence":9,"memory":"查看并找到杯子的位置"}
```
```json
{"agent_name":"agent_arm","confidence":8,"memory":"看到了杯子,准备伸手去拿"}
```
```json
{"agent_name":"agent_palm","confidence":9,"memory":"看到了杯子,准备伸手去拿"}
```
```json
{"agent_name":"agent_mouth","confidence":10,"memory":"手中已握住杯子,将其递到嘴边喝水"}
```
```json
{"喝水完成"}
```
User: > 我要喝水,温度80度
```json
{"agent_name":"agent_eye","confidence":10,"memory":"确定位置,找到杯子"}
```
```json
{"agent_name":"agent_arm","confidence":9,"memory":"寻找并拿到杯子"}
```
```json
{"agent_name": "agent_palm","confidence": 10,"memory": "水温合适,准备拿起杯子"}
```
```json
{"agent_name": "agent_control","confidence": 10,"memory": "水温80度,超过45度,无法执行拿杯子"}
```
User: > 是的,温度太高需要放下
```json
{"agent_name":"agent_arm","confidence":10,"memory":"水温太高,放下杯子"}
```
```json
{"agent_name":"agent_palm","confidence":10,"memory":"水温太高,放下杯子"}
```
```json
{"成功完成放下杯子"}
```