资讯动态

用 Instructor 实现 Universal Self Prompting:无标注数据驱动的两阶段自适应示例生成与单次推理

发布时间:2026/9/15 20:07:43 来源:尧图企业网站定制
用 Instructor 实现 Universal Self Prompting无标注数据驱动的两阶段自适应示例生成与单次推理【免费下载链接】instructorstructured outputs for llms项目地址: https://gitcode.com/GitHub_Trending/in/instructorUniversal Self PromptingUSP通用自提示是一种不依赖人工标注数据的少样本提示技术先让 LLM 在一个测试数据集上批量生成候选回答再依据任务类型选择与 COSP 不同的三种评分机制挑选高质量示例最终**仅用一次前向传递greedy decoding**得出最终预测。本文将结合 docs/prompting/ensembling/usp.md 的完整定义与 instructor 的异步客户端源码给出可直接运行的分类实现并逐段拆解平衡采样与置信度加权的工程细节。核心思想与 COSP 同源但更任务自适应USP 与 Consistency Based Self Adaptive Prompting (COSP) 同属无标注自适提示家族二者都把流程分成两个阶段生成示例Generate Examples用测试数据集提示 LLM让模型生成一批候选响应回答问题Answer Query从这批模型自生成的响应中挑选少量作为 few-shot 示例再次提示 LLM 得到最终预测。USP 与 COSP 的关键区别在于示例质量的评估方式COSP 对所有任务统一使用归一化熵 重复度repetitiveness作为评分信号详见 cosp.mdUSP 则把任务划分为三类为每一类定制专属的评分函数因而能对生成的单个示例做出更贴合任务形态的质量评估。此外USP 在最终阶段不做多次采样与多数投票而是采用单次前向传递 贪心解码greedy decoding得到答案。相比之下 COSP 第二步还要通过 Self-Consistency 多次采样投票而 USP 通过把好示例直接注入 prompt 来压缩成本。USP 完整流程上图展示了 USP 的自适应闭环未标注数据集通过零样本查询进入 LLM 产生第一阶段输出Stage 1 outputs随后根据任务类别用Logit 熵 / 一致性 / 重叠度ROUGE之一筛选出高质量模型生成的伪演示Model-generated pseudo-demos这些伪演示与测试集查询合并后再次进入 LLM最终输出预测结果。阶段一生成候选示例给定一组提示词prompt首先让模型为每条提示生成候选响应。与 COSP 不同USP 不再用熵与重复度统一打分而是要求用户事先指定任务所属类别再使用下列三种评估方法之一衡量生成响应质量。需要特别注意的是对于Short Form 与 Long Form 生成类任务每条提示需要生成 m 个不同的样本以便计算分布与两两相似度而分类任务不生成 m 个样本其评分直接基于 logits。类别一分类任务Classification——基于 Logits 的归一化概率熵分类任务使用 LLM 对每个标签的原始 logits 计算归一化概率再求信息熵$$ F_{CLS}(p^{(j)}|d^{(j)}) : -\sum_{c \in C} P(c|d^{(j)}) \log P(c|d^{(j)}) $$简单来说取出每个标签对应 token 的原始 logit → 用 softmax 归一化 → 对各标签概率与其对数概率的乘积求和。此外还尽量采样足够多的查询使每个类别下的预测数量均衡避免模型对某些类别产生偏向。对应任务示例自然语言推理Natural Language Inference、主题分类Topic Classification、情感分析Sentiment Analysis。类别二短文本生成Short Form Generation——去掉归一化项的熵短文本生成沿用与 COSP 类似的熵公式但去掉归一化项$$ \mathcal{H}\left(x^{(i)} \mid \left{\hat{y}j^{(i)}\right}{j1}^m\right) \frac{\sum_{\alpha1}^u \hat{p}\left(\hat{y}{\alpha}^{(i)}\right) \log \hat{p}\left(\hat{y}{\alpha}^{(i)}\right)}{\log m}, $$其中 $u$ 为 $m$ 个生成回答中互不相同的回答数$\hat{p}(\hat{y}_\alpha^{(i)})$ 是该唯一答案在全部 $m$ 个回答中的出现频率。低熵意味着模型对答案更笃定通常与正确性正相关。对应任务示例问答Question Answering、句子补全Sentence Completion。类别三长文本生成Long Form Generation——两两 ROUGE 平均分长文本生成使用m 个响应之间两两配对的平均 ROUGE 分数来衡量一致性如果模型对同一提示多次生成的结果在字面上高度重合ROUGE 高说明该提示更可能产出稳定、可信的输出。对应任务示例文本摘要Text Summarization、机器翻译Machine Translation。三种评分机制的价值在于不同任务形态需要不同的一致性定义——分类看 logits 熵短文本看答案分布熵长文本看表面重叠度。这正是 USP 名称中Universal通用与自适应的体现。阶段二生成单一回答选定示例后第二阶段非常简单把在所选指标上得分最高的少数几个示例追加到 prompt 中调用一次模型即可。最终答案是单次前向传递 greedy decoding因此推理成本低于需要多次采样的 COSP / Self-Consistency 方案。基于 Instructor 的完整实现平衡采样的情感分类下面这段实现来自 usp.md它演示了分类场景下的完整流程跨类别平衡采样 置信度加权最终通过单次推理调用生成答案。from pydantic import BaseModel from typing import Literal import instructor import asyncio from collections import defaultdict class Classification(BaseModel): chain_of_thought: str label: Literal[Happy, Angry, Sadness] confidence: Literal[ Uncertain, Somewhat Confident, Confident, Highly Confident ] def confidence_score(self) - int: confidence_order { Highly Confident: 4, Confident: 3, Somewhat Confident: 2, Uncertain: 1, } return confidence_order[self.confidence] client instructor.from_provider(openai/gpt-4o-mini, async_clientTrue) async def generate_prediction(query: str): return ( await client.create( modelgpt-5.4-mini, messages[ { role: user, content: fClassify the following query {query} into one of the following categories: Happy, Angry, Sadness, } ], response_modelClassification, ), query, ) async def generate_predictions(queries: list[str]) - list[tuple[Classification, str]]: return await asyncio.gather(*[generate_prediction(query) for query in queries]) def get_balanced_sample(predictions: list[tuple[Classification, str]], k: int): label_to_queries: dict[str, list[tuple[Classification, str]]] defaultdict(list) for prediction in predictions: label_to_queries[prediction[0].label].append(prediction) num_classes len(label_to_queries) num_samples_per_class k // num_classes res: list[str] [] for label, label_queries in label_to_queries.items(): label_queries sorted( label_queries, keylambda x: x[0].confidence_score(), reverseTrue ) label_queries [ label_queries[1] for label_queries in label_queries[:num_samples_per_class] ] res.extend([f{query} ({label}) for query in label_queries]) return res async def generate_response_with_examples(query: str, examples: list[str]): formatted_examples \n.join(examples) return await client.create( modelgpt-4o, response_modelClassification, messages[ { role: system, content: f You are a helpful assistant that classifies queries into one of the following categories: Happy, Angry, Sadness. Here are some samples of queries and their categories: examples {formatted_examples} /examples Here is a user query to classify query {query} /query , }, ], ) if __name__ __main__: examples [ i do feel that running is a divine experience and that i can expect to have some type of spiritual encounter , i get giddy over feeling elegant in a perfectly fitted pencil skirt , i plan to share my everyday life stories traveling adventures inspirations and handmade creations with you and hope you will also feel inspired , i need to feel the dough to make sure its just perfect , i found myself feeling a little discouraged that morning , i didnt really feel that embarrassed, i feel like a miserable piece of garbage, i feel like throwing away the shitty piece of shit paper , i feel irritated and rejected without anyone doing anything or saying anything , i feel angered and firey, im feeling bitter today my mood has been strange the entire day so i guess its that , i just feel really violent right now, i know there are days in which you feel distracted, ] labels asyncio.run(generate_predictions(examples)) balanced_sample get_balanced_sample(labels, 3) for sample in balanced_sample: print(sample) i do feel that running is a divine experience and that i can expect to have some type of spiritual encounter (Happy) # i feel like a miserable piece of garbage (Sadness) # i feel like throwing away the shitty piece of shit paper (Angry) response asyncio.run( generate_response_with_examples( i feel furious that right to life advocates can and do tell me how to live and die through lobbying and supporting those politicians sympathic to their views , balanced_sample, ) ) print(response.model_dump_json(indent2)) { chain_of_thought: The user expresses feelings of anger and frustration specifically directed at right to life advocates. The language used, such as furious, indicates a high level of emotion associated with anger., label: Angry, confidence: Highly Confident } 逐步拆解从结构化输出到平衡采样1. 用 Pydantic 定义结构化响应模型Classification包含三个字段chain_of_thought推理过程、labelLiteral[Happy, Angry, Sadness]限定三分类、confidence四级置信度。其中confidence_score()方法把离散的置信度映射为 1–4 的整数分数供后续排序使用。这正是 Instructor 的典型用法response_model决定输出的 JSON 结构字段描述与类型约束共同驱动 LLM 生成可校验的结果。2. 通过from_provider创建异步客户端client instructor.from_provider(openai/gpt-4o-mini, async_clientTrue)从 instructor/v2/auto_client.py 的源码可以看到from_provider接受provider/model-name格式的模型字符串async_clientTrue时返回AsyncInstructor实例**kwargs会透传给各 provider 实现如缓存、provider 特有参数。因此在generate_prediction中使用await client.create(...)是合法且推荐的异步调用方式。3. 批量生成候选预测generate_predictions通过asyncio.gather并发地对全部示例查询执行结构化分类返回(Classification, query)元组列表。这里对应 USP 的阶段一用测试数据生成候选响应。4. 平衡采样 置信度加权get_balanced_sample(predictions, k)是 USP 文档中分类任务要保证各类别样本均衡这一要点的工程落地先用defaultdict(list)按label分组由num_classes计算每个类别应取k // num_classes个样本每个类别内部按confidence_score()降序排序优先取模型更自信的样本最终拼接为query (label)格式的示例字符串列表。在示例数据上取k33 个类别会得到Sadness、Angry各一例以及一个Happy样本从而保证最终 prompt 中的示例类别均衡、不偏向任一标签。5. 注入示例并单次推理generate_response_with_examples把格式化后的示例放入 system 消息的examples块中与待分类的query一起交给模型只调用一次即返回Classification。对应 USP 的阶段二单次前向传递 greedy decoding。最后通过model_dump_json(indent2)打印结构化结果示例输出为label: Angry、confidence: Highly Confident。三种评分机制的选用指南任务类别代表任务评分方法是否采样 m 个样本Classification自然语言推理、主题分类、情感分析基于 raw logits 的归一化标签概率熵 $F_{CLS}$否改用平衡采样 置信度Short Form Generation问答、句子补全类似 COSP 的熵公式无归一化项是Long Form Generation文本摘要、机器翻译m 个响应两两之间的平均 ROUGE 分数是分类任务之所以不采样 m 次是因为其置信度可以直接从 logits 中读取生成类任务没有天然的概率信号只能通过多次采样m 个样本后观察答案分布的熵或表面重叠度来间接估计一致性。与仓库中其他 Ensembling 技术的定位在 docs/prompting/index.md 的 Ensembling 分类中USP 被归类为Task-Specific Selection按任务选择示例适用于专业化领域任务与之相邻的 Universal Self-Consistency 则让第二个 LLM 从多条候选推理链中挑选最一致的答案而非直接投票适合输出格式多样的场景。三者对比Self-Consistency多次采样 多数投票不评估示例质量COSP归一化熵 重复度挑选示例最后再做 self-consistency 投票USP按任务类别定制评分挑选示例最终只推理一次成本最低。实践建议与注意事项必须事先指定任务类别USP 的三套评分机制依赖用户对任务形态的判断错误分类会直接导致评分失真分类任务的类别均衡示例数量k应能被类别数整除并配合confidence_score之类的自报告置信度排序优先选择模型有把握的样本生成类任务合理设置 mShort/Long Form 任务的评分依赖 $m$ 个样本的分布/重叠度$m$ 过小则熵与 ROUGE 估计不稳定$m$ 过大则阶段一成本上升结构化输出贯穿全流程无论是阶段一的候选生成还是阶段二的最終预测都建议用response_model约束输出本示例中为chain_of_thought、label、confidence让置信度这类自报告信号可作为排序依据成本特性USP 的最大收益是最终阶段仅一次前向传递整体成本集中在阶段一的批量采样上适合离线准备示例、在线低延迟推理的场景。参考本文核心内容基于仓库文档 docs/prompting/ensembling/usp.md流程示意图见 docs/img/universal_self_adaptive_prompting.pngfrom_provider的实现与参数说明见 instructor/v2/auto_client.py姊妹技术 COSP 见 docs/prompting/ensembling/cosp.mdUniversal Self-Consistency 见 docs/prompting/ensembling/universal_self_consistency.md完整技术地图见 docs/prompting/index.md。【免费下载链接】instructorstructured outputs for llms项目地址: https://gitcode.com/GitHub_Trending/in/instructor创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价