此存儲庫中的食譜從那以後移至Prodigy,並在那里維持。他們甚至很快就會隨著Spacy-LLM支持的出現而進行升級,該支持具有更好的提示和多個LLM提供商。這就是為什麼我們選擇歸檔此存儲庫的原因,以便我們可以直接將這些食譜直接保留為Spacy和Prodigy的一部分。
您可以通過查看文檔中的大型語言模型部分來了解更多信息。
該存儲庫包含有關如何將零和幾次學習與小註釋工作相結合的示例代碼,以獲得具有最大效率的高質量數據集。具體來說,我們使用OpenAI可用的大型語言模型為我們提供了一組初始的預測,然後在本地機器上旋轉一個天體實例來瀏覽這些預測並策劃它們。這使我們能夠很快獲得一個金標準數據集,並訓練適合我們確切需求和用例的較小監督模型。

確保安裝Prodigy以及其他一些Python依賴性:
python -m pip install prodigy -f https://[email protected]
python -m pip install -r requirements.txt用XXXX-XXXX-XXXX-XXXX是您的個人神秘許可證密鑰。
然後,從OpenAi.com創建一個新的API密鑰或獲取現有的API密鑰。記錄秘密密鑰以及組織密鑰,並確保將其作為環境變量可用。例如,將它們設置在根目錄中的.env文件中:
OPENAI_ORG = "org-..."
OPENAI_KEY = "sk-..."
ner.openai.correct :零或幾次學習的NER註釋此食譜標記了從大語言模型獲得的實體預測,並允許您將其標記為正確,或者手動策劃它們。這使您可以通過零拍或幾次學習快速收集金標準數據集。這很像在prodi.gy中使用標準的ner.correct ,但是我們使用GPT-3作為後端模型來做出預測。
python -m prodigy ner.openai.correct dataset filepath labels [--options] -F ./recipes/openai_ner.py| 爭論 | 類型 | 描述 | 預設 |
|---|---|---|---|
dataset | str | prodigy數據集將註釋保存到。 | |
filepath | 小路 | 通往.jsonl數據的路徑。數據至少應包含一個"text"字段。 | |
labels | str | 定義模型應該預測的NER標籤的逗號分隔列表。 | |
--lang , -l | str | 輸入數據的語言 - 將用於獲得相關的令牌。 | "en" |
--segment , -S | 布爾 | 當應將示例分為句子時,要設置的標誌。默認情況下,顯示了完整的輸入文章。 | False |
--model , -m | str | GPT-3模型用於初始預測。 | "text-davinci-003" |
--prompt_path , -p | 小路 | 通往.jinja2提示模板的路徑。 | ./templates/ner_prompt.jinja2 |
--examples-path , -e | 小路 | 示例的途徑以幫助定義任務。該文件可以是.yml,.yaml或.json。如果設置為None ,則應用零射擊學習。 | None |
--max-examples , -n | int | 最大示例數量要包括在OpenAi提示中。如果設置為0,即使有示例可用,也始終應用零射擊學習。 | 2 |
--batch-size , -b | int | 查詢的批次大小發送到OpenAI API。 | 10 |
--verbose , -v | 布爾 | 標誌以將額外信息打印到終端。 | False |
假設我們想從我們從烹飪子雷迪特獲得的一些文本中識別出菜餚,成分和烹飪設備。我們將將文本發送到由OpenAI託管的GPT-3,並提供註釋提示,向語言模型解釋我們想要的預測類型。像:
From the text below, extract the following entities in the following format:
dish: <comma delimited list of strings>
ingredient: <comma delimited list of strings>
equipment: <comma delimited list of strings>
Text:
...
我們在.jinja2文件中定義了此提示的定義,該文件還描述瞭如何附加幾次學習的示例。您可以創建自己的模板,並使用--prompt-path或-p選項將其提供給食譜。此外,使用--examples-path或-e ,您可以設置包含其他示例的.y(a)ml或.json文件的文件路徑:
python -m prodigy ner.openai.correct my_ner_data ./data/reddit_r_cooking_sample.jsonl " dish,ingredient,equipment " -p ./templates/ner_prompt.jinja2 -e ./examples/ner.yaml -n 2 -F ./recipes/openai_ner.py從OpenAI API接收結果後,Prodigy配方將預測轉換為可以用Prodigy渲染的註釋任務。該任務甚至顯示了我們從語言模型中獲得的原始提示以及原始答案。

在這裡,我們看到該模型從一開始就可以正確識別菜餚,成分和烹飪設備!
該食譜還提供--verbose或-v選項,其中包括收到流量時終端上的確切提示和響應。請注意,由於對API的請求進行了批處理,因此您可能需要稍微滾動一點才能找到當前的提示。
在某個時候,您可能會在OpenAI語言模型的預測中註意到一個錯誤。例如,我們注意到在此示例中識別烹飪設備的錯誤:

如果您看到這些系統錯誤,則可以通過糾正示例,然後在Prodigy UI右上方選擇小的“標誌”圖標來將預測引導到正確的方向:

一旦您在Prodigy接口上擊中Accept ,標記的示例將自動拾取,並將作為提示的一部分發送到OpenAI API的示例。
筆記
由於Prodigy批次批量這些請求,因此在將下一批提示發送到OpenAI之後,提示將稍有延遲更新。您可以嘗試使批處理大小(--batch-size或-b)較小以使更改更早生效,但這可能會對註釋工作流的速度產生負面影響。
ner.openai.fetch :提取示例ner.openai.correct食譜在註釋時從OpenAI中獲取了示例,但我們還提供了一個可以預先獲取大量示例的食譜。
python -m prodigy ner.openai.fetch input_data.jsonl predictions.jsonl " dish,ingredient,equipment " -F ./recipes/ner.py這將創建一個可以加載的ner.manual配方的predictions.jsonl 。
請注意,OpenAI API一次要求過多數據時可能會返回“ 429請求太多”錯誤 - 在這種情況下,最好一次確保您一次僅請求100個左右的示例。
策劃了一組預測後,您可以以db-out導出結果:
python -m prodigy db-out my_ner_data > ner_data.jsonl導出的註釋的格式包含您在下游訓練較小模型所需的所有數據。數據集中的每個示例都包含原始文本,令牌,跨度註釋表示實體等。
您還可以使用數據data-to-spacy導出到Spacy的二進制格式。這種格式使您可以作為Spacy Doc對象加載註釋,這對於進一步轉換可以方便。 data-to-spacy命令還使使用Spacy訓練NER模型變得容易。首先,您導出數據,將火車數據指定為總計的20%:
python -m prodigy data-to-spacy ./data/annotations/ --ner my_ner_data -es 0.2然後,您可以用Spacy或Prodigy訓練模型:
python -m spacy train ./data/annotations/config.cfg --paths.train ./data/annotations/train.spacy --paths.dev ./data/annotations/dev.spacy -o ner-model這將將模型保存到ner-model/目錄。
我們還提供了一個實驗腳本,以加載.spacy二進制格式,並使用HuggingFace transformers庫來訓練模型。您可以使用剛導出的相同數據並像這樣運行腳本:
# First you need to install the HuggingFace library and requirements
pip install -r requirements_train.txt
python ./scripts/train_hf_ner.py ./data/annotations/train.spacy ./data/annotations/dev.spacy -o hf-ner-model所得模型將保存到hf-ner-model/目錄。
textcat.openai.correct :零或幾次學習的TextCat註釋此食譜使我們能夠在大型語言模型的幫助下更快地對文本進行分類。它還提供了解釋為什麼選擇特定標籤的“原因”。
python -m prodigy textcat.openai.correct dataset filepath labels [--options] -F ./recipes/openai_textcat.py| 爭論 | 類型 | 描述 | 預設 |
|---|---|---|---|
dataset | str | prodigy數據集將註釋保存到。 | |
filepath | 小路 | 通往.jsonl數據的路徑。數據至少應包含一個"text"字段。 | |
labels | str | 定義文本分類標籤的逗號分隔列表該模型應該預測。 | |
--lang , -l | str | 輸入數據的語言 - 將用於獲得相關的令牌。 | "en" |
--segment , -S | 布爾 | 當應將示例分為句子時,要設置的標誌。默認情況下,顯示了完整的輸入文章。 | False |
--model , -m | str | GPT-3模型用於初始預測。 | "text-davinci-003" |
--prompt-path , -p | 小路 | 通往.jinja2提示模板的路徑。 | ./templates/textcat_prompt.jinja2 |
--examples-path , -e | 小路 | 示例的途徑以幫助定義任務。該文件可以是.yml,.yaml或.json。如果設置為None ,則應用零射擊學習。 | None |
--max-examples , -n | int | 最大示例數量要包括在OpenAi提示中。如果設置為0,即使有示例可用,也始終應用零射擊學習。 | 2 |
--batch-size , -b | int | 查詢的批次大小發送到OpenAI API。 | 10 |
--exclusive-classes , -E | 布爾 | 標誌以使分類任務排他性。 | False |
--verbose , -v | 布爾 | 標誌以將額外信息打印到終端。 | False |
textcat配方可用於二進制,多類和多標籤文本分類。您可以通過在--labels參數中傳遞適當數量的標籤來設置此設置;例如,通過單個標籤將其變成二進制分類,依此類推。我們將在程序中討論每個部分。
假設我們想知道是否有一個特定的Reddit評論在談論食物食譜。我們將將文本發送到GPT-3,並提供指示我們想要的預測的提示。
From the text below, determine wheter or not it contains a recipe. If it is a
recipe, answer "accept." If it is not a recipe, answer "reject."
Your answer should only be in the following format:
answer: <string>
reason: <string>
Text:
對於二進制分類,我們希望GPT-3如果給定文本是食物配方,否則拒絕“接受”。然後在UI中突出顯示GPT-3的建議。我們可以按Accept (Check Mark)按鈕將文本作為正面示例包括在內,或者按拒絕(Cross Mark)按鈕,如果是一個負示例。
python -m prodigy textcat.openai.correct my_binary_textcat_data data/reddit_r_cooking_sample.jsonl --labels recipe -F recipes/openai_textcat.py
現在,假設我們要將Reddit註釋分類為食譜,反饋或問題。我們可以編寫以下提示:
Classify the text below to any of the following labels: recipe, feedback, question.
The task is exclusive, so only choose one label from what I provided.
Your answer should only be in the following format:
answer: <string>
reason: <string>
Text:
然後,我們可以使用此食譜來通過將三個標籤傳遞給--labels參數來處理多標籤和多類案例。我們還應該設置--exclusive-classes標誌以渲染單選ui:
python -m prodigy textcat.openai.correct my_multi_textcat_data data/reddit_r_cooking_sample.jsonl
--labels recipe,feedback,question
--exclusive-classes
-F recipes/openai_textcat.py
我們將這些提示寫為.jinja2模板,也可以以幾次學習的示例進行示例。您可以創建自己的模板,並使用--prompt-path或-p選項將其提供給食譜。此外,使用--examples-path或-e ,您可以設置包含其他示例的.y(a)ml或.json文件的文件路徑。您還可以在這些示例中添加上下文,因為我們觀察到它可以改善輸出:
python -m prodigy textcat.openai.correct my_binary_textcat_data
./data/reddit_r_cooking_sample.jsonl
--labels recipe
--prompt-path ./templates/textcat_prompt.jinja2
--examples-path ./examples/textcat_binary.yaml -n 2
-F ./recipes/openai_textcat.py與NER食譜類似,此食譜還將預測轉換為可以用Prodigy渲染的註釋任務。對於二進制分類,我們將classification接口與自定義HTML元素一起使用,而對於多類或多類文本分類,我們使用了choice註釋接口。請注意,我們在UI中包括原始提示和OpenAI響應。
最後,您可以使用--verbose或-v標誌在終端上顯示確切的提示和響應。請注意,由於對API的請求進行了批處理,因此您可能需要稍微滾動一點才能找到當前的提示。
與NER配方類似,您還可以通過糾正示例,然後在Prodigy UI右上角選擇小“標誌”圖標來將預測引導到正確的方向:

點擊Prodigy界面上的“接受”按鈕後,將在提示的一部分中拾取標記的示例並將其添加到發送到OpenAI API的幾個示例中。
筆記
由於Prodigy批次批量這些請求,因此在將下一批提示發送到OpenAI之後,提示將稍有延遲更新。您可以嘗試使批處理大小(--batch-size或-b)較小以使更改更早生效,但這可能會對註釋工作流的速度產生負面影響。
textcat.openai.fetch :獲取文本分類示例textcat.openai.fetch食譜使我們能夠預先獲取大量示例。當您使用高度影響的數據並且僅對罕見示例感興趣時,這很有幫助。
python -m prodigy textcat.openai.fetch input_data.jsonl predictions.jsonl --labels Recipe -F ./recipes/openai_textcat.py這將創建一個可以使用textcat.manual配方加載的predictions.jsonl文件。
請注意,OpenAI API一次要求時可能會返回“ 429請求”錯誤 - 在這種情況下,最好確保您一次僅請求100個左右的示例,並查看API的速率限制。
textcat.openai.fetch食譜適合與存在嚴重類失衡的數據集。通常,您需要找到稀有類的示例,而不是註釋隨機樣本。從那裡,您想將它們置於訓練一個體面的模型等。
這是像OpenAI這樣的大型語言模型可能會有所幫助的地方。
使用REDDIT R/烹飪數據集,我們提示Openai尋找類似於食物食譜的評論。我們沒有註釋10,000個示例,而是運行了textcat.openai.fetch並獲得了145個積極的類。在這145個示例中,有114個是真正的陽性(精度為79%)。然後,我們檢查了1,000個負面示例,並發現了12例假陰性病例(98%的召回)。
理想情況下,一旦我們完全註釋了數據集,我們就可以訓練一種監督模型,該模型比依靠零射擊預測生產要好。運行成本很低,更容易管理。
策劃了一組預測後,您可以以db-out導出結果:
python -m prodigy db-out my_textcat_data > textcat_data.jsonl導出的註釋的格式包含您在下游訓練較小模型所需的所有數據。數據集中的每個示例都包含原始文本,令牌,跨度註釋表示實體等。
您還可以使用數據data-to-spacy導出到Spacy的二進制格式。這種格式使您可以作為Spacy Doc對象加載註釋,這對於進一步轉換可以方便。 data-to-spacy命令還使用Spacy訓練文本分類模型變得容易。首先,您導出數據,將火車數據指定為總計的20%:
# For binary textcat
python -m prodigy data-to-spacy ./data/annotations/ --textcat my_textcat_data -es 0.2
# For multilabel textcat
python -m prodigy data-to-spacy ./data/annotations/ --textcat-multilabel my_textcat_data -es 0.2然後,您可以用Spacy或Prodigy訓練模型:
python -m spacy train ./data/annotations/config.cfg --paths.train ./data/annotations/train.spacy --paths.dev ./data/annotations/dev.spacy -o textcat-model這將將模型保存到textcat-model/ Directory中。
terms.openai.fetch :根據查詢獲取短語和術語該食譜生成了從大語言模型獲得的術語和短語。這些術語可以策劃並將其變成模式文件,這可以幫助下游註釋任務。
python -m prodigy terms.openai.fetch query filepath [--options] -F ./recipes/openai_terms.py| 爭論 | 類型 | 描述 | 預設 |
|---|---|---|---|
query | str | 查詢發送到Openai | |
output_path | 小路 | 保存輸出的路徑 | |
--seeds , -s | str | 一個或多個分離的種子短語。 | "" |
--n , -n | int | 生成的最少項目數量 | 100 |
--model , -m | str | GPT-3用於完成的型號 | "text-davinci-003" |
--prompt-path , -p | 小路 | 通往jinja2提示模板的路徑 | templates/terms_prompt.jinja2 |
--verbose , -v | 布爾 | 將額外信息打印到終端 | False |
--resume , -r | 布爾 | 通過從輸出文件中加載文本示例中的恢復 | False |
--progress , -pb | 布爾 | 打印食譜的進度。 | False |
--temperature , -t | 漂浮 | OpenAI溫度參數 | 1.0 |
--top-p , --tp | 漂浮 | OpenAI TOP_P參數 | 1.0 |
--best-of , -bo | int | openai best_of param” | 10 |
--n-batch , -nb | int | Openai批處理大小參數 | 10 |
--max-tokens , -mt | int | 最大令牌要生成每個通話 | 100 |
假設您有興趣檢測文本中的滑板技巧,那麼您可能想從已知技巧的術語列表開始。您可能需要從以下查詢開始:
# Base behavior, fetch at least 100 terms/phrases
python -m prodigy terms.openai.fetch " skateboard tricks " tricks.jsonl --n 100 --prompt-path templates/terms_prompt.jinja2 -F recipes/openai_terms.py這將產生一個提示,該提示要求嘗試生成至少100個“滑板技巧”的示例。 OpenAI可以生成的代幣數量有一個上限,但是此食譜將嘗試繼續收集條款,直到達到指定的金額為止。
如果您想更精確,則可以選擇使查詢更加精心詳細,但也可以選擇通過--seeds添加一些種子術語。這些將作為開始示例,以幫助將Openai轉向正確的方向。
# Base behavior but with seeds
python -m prodigy terms.openai.fetch " skateboard tricks " tricks.jsonl --n 100 --seeds " kickflip,ollie " --prompt-path templates/terms_prompt.jinja2 -F recipes/openai_terms.py收集許多示例可能需要一段時間,因此隨著請求的發送,通過--progress展示進度可能會有所幫助。
# Adding progress output as we wait for 500 examples
python -m prodigy terms.openai.fetch " skateboard tricks " tricks.jsonl --n 500 --progress --seeds " kickflip,ollie " --prompt-path templates/terms_prompt.jinja2 -F recipes/openai_terms.py收集了一些示例後,您可能需要生成更多。您可以選擇從以前的輸出文件中繼續。這將有效地將這些例子重新使用作為提示的種子。
# Use the `--resume` flag to re-use previous examples
python -m prodigy terms.openai.fetch " skateboard tricks " tricks.jsonl --n 50 --resume --prompt-path templates/terms_prompt.jinja2 -F recipes/openai_terms.py食譜完成後,您將有一個tricks.jsonl文件,其中具有如下的內容:
{ "text" : " pop shove it " , "meta" :{ "openai_query" : " skateboard tricks " }}
{ "text" : " switch flip " , "meta" :{ "openai_query" : " skateboard tricks " }}
{ "text" : " nose slides " , "meta" :{ "openai_query" : " skateboard tricks " }}
{ "text" : " lazerflip " , "meta" :{ "openai_query" : " skateboard tricks " }}
{ "text" : " lipslide " , "meta" :{ "openai_query" : " skateboard tricks " }}
...現在,您在磁盤上有一個tricks.jsonl文件,其中包含滑板技巧,但是您不能假設所有這些都是準確的。下一步將是查看術語,您可以使用textcat.manual 。
# The tricks.jsonl was fetched from OpenAI beforehand
python -m prodigy textcat.manual skateboard-tricks-list tricks.jsonl --label skateboard-tricks這會生成一個看起來像這樣的接口:

您可以手動接受或拒絕每個示例,當您完成註釋後,可以通過terms.to-patterns帶註釋的文本導出到模式文件中。
# Generate a `patterns.jsonl` file.
python -m prodigy terms.to-patterns skateboard-tricks-list patterns.jsonl --label skateboard-tricks --spacy-model blank:en完成食譜後,您將有一個patterns.jsonl文件,其中具有類似的內容:
{ "label" : " skateboard-tricks " , "pattern" :[{ "lower" : " pop " },{ "lower" : " shove " },{ "lower" : " it " }]}
{ "label" : " skateboard-tricks " , "pattern" :[{ "lower" : " switch " },{ "lower" : " flip " }]}
{ "label" : " skateboard-tricks " , "pattern" :[{ "lower" : " nose " },{ "lower" : " slides " }]}
{ "label" : " skateboard-tricks " , "pattern" :[{ "lower" : " lazerflip " }]}
{ "label" : " skateboard-tricks " , "pattern" :[{ "lower" : " lipslide " }]}
...Openai對及時尺寸有嚴格的限制。您的及時要及時大於4079代幣。不幸的是,這意味著您可以生成的術語列表的大小有限制。當發生這種情況時,食譜將報告一個錯誤,但是很高興意識到此限制。
ab.openai.prompts :提示的A/B評估該食譜的目的是快速允許某人以可量化和盲目的方式比較兩個提示的輸出質量。
python -m prodigy ab.openai.prompts dataset inputs_path display_template_path prompt1_template_path prompt2_template_path [--options] -F ./recipes/openai_ab.py| 爭論 | 類型 | 描述 | 預設 |
|---|---|---|---|
dataset | str | Prodigy數據集可將答案保存到 | |
inputs_path | 小路 | 通往JSONL輸入的路徑 | |
display_template_path | 小路 | 總結參數的模板 | |
prompt1_template_path | 小路 | 通往第一個Jinja2提示模板的路徑 | |
prompt2_template_path | 小路 | 通往第二個Jinja2提示模板的路徑 | |
--model , -m | str | GPT-3用於完成的型號 | "text-davinci-003" |
--batch-size , -b | int | 批次大小發送到OpenAI API | 10 |
--verbose , -v | 布爾 | 將額外信息打印到終端 | False |
--no-random , -NR | 布爾 | 不要隨機化哪種註釋顯示為正確 | False |
--repeat , -r | int | 多久向Openai發送相同提示的多久一次 | 1 |
例如,讓我們嘗試產生幽默的狂熱。為此,我們首先需要構造兩個表示發送到OpenAI的提示的Jinja文件。
templates/ab/prompt1.jinja2 Write a haiku about {{topic}}.
templates/ab/prompt2.jinja2 Write an incredibly hilarious haiku about {{topic}}. So funny!
您可以通過構造帶有所需參數的.jsonl文件來為這些提示提供變量。在這種情況下,我們需要確保考慮{{topic}} 。
這是一個可以工作的示例.jsonl文件。
data/ab_example.jsonl{ "id" : 0 , "prompt_args" : { "topic" : " star wars " }}
{ "id" : 0 , "prompt_args" : { "topic" : " kittens " }}
{ "id" : 0 , "prompt_args" : { "topic" : " the python programming language " }}
{ "id" : 0 , "prompt_args" : { "topic" : " maths " }}筆記
prompt_args下的所有參數將通過以渲染Jinja模板。id是強制性的,可用於以後分析中識別組。
我們幾乎可以評估了,但是此食譜需要一個最終的Jinja2模板。這個不會用於生成提示,但它將生成一個有用的標題,以提醒當前任務的註釋者。這是這樣的模板的示例。
templates/ab/input.jinja2 A haiku about {{topic}}.
當您將所有這些模板放在一起時,您可以開始註釋。下面的命令啟動註釋接口,還使用--repeat 4選項。這將確保每個主題至少將其提示至少4次。
python -m prodigy ab.openai.prompts haiku data/ab_example.jsonl templates/ab/input.jinja2 templates/ab/prompt1.jinja2 templates/ab/prompt2.jinja2 --repeat 5 -F recipes/openai_ab.py
這就是註釋接口的樣子:

當您查看此界面時,您會注意到標題模板是渲染的,並且可以從兩個選項中選擇。這兩個選項都是由兩個提示模板生成的OpenAI的響應。您還可以在選擇菜單的右下角看到prompt_args 。
從這裡,您可以註釋您喜歡的示例並收集可能幫助您確定哪個提示最好的數據。
註釋後,您將概述結果概述。
=========================== Evaluation results ===========================
✔ You preferred prompt1.jinja2
prompt1.jinja2 11
prompt2.jinja2 5
但是您也可以從數據庫中獲取原始註釋以進行進一步分析。
python -m prodigy db-out haiku
有很多有趣的後續實驗,以及許多將基本思想調整到不同任務或數據集的方法。我們也有興趣嘗試不同的提示。目前尚不清楚要求註釋的格式可能會改變模型的預測,或者是否有較短的提示也可能會執行。我們還想運行一些端到端的實驗。