OpenAI前研究科學(xué)家開(kāi)源面向未來(lái)的提示工程庫(kù) ell,重新定義提示工程
在前面的文章里,我們介紹了很多有關(guān)提示工程的前沿技術(shù)與工具,它們都揭示了一個(gè)共識(shí)性方向,就是提示工程不僅僅是人機(jī)對(duì)話的語(yǔ)言藝術(shù),更是一個(gè)持續(xù)迭代優(yōu)化的系統(tǒng)性軟件工程。近日,OpenAI前研究科學(xué)家william對(duì)外正式開(kāi)源了一個(gè)號(hào)稱面向未來(lái)的提示工程庫(kù),名為 ell[1],它將提示視為函數(shù),并提供了一系列強(qiáng)大的工具來(lái)優(yōu)化和管理提示。
在這個(gè)庫(kù)中有一些核心設(shè)計(jì)理念值得大家學(xué)習(xí)借鑒。

提示是程序,而不是字符串
在傳統(tǒng)的提示工程中,我們通常將提示視為簡(jiǎn)單的字符串。然而,ell 顛覆了這一觀念,將提示視為程序。通過(guò)這種方式,我們可以將提示封裝成獨(dú)立的子程序,稱為語(yǔ)言模型程序(Language Model Program, LMP)。這些 LMP 是完全封裝的函數(shù),可以生成字符串提示或消息列表,發(fā)送到各種多模態(tài)語(yǔ)言模型。
讓我們從一個(gè)傳統(tǒng)的 API 調(diào)用示例開(kāi)始,看看如何使用 ell 實(shí)現(xiàn)相同的功能。以下是使用 OpenAI Chat Completion API 的簡(jiǎn)單示例:
import openai
openai.api_key = "your-api-key-here"
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Say hello to Sam Altman!"}
]
response = openai.ChatCompletion.create(
model="gpt-4o",
messages=messages
)
print(response['choices'][0]['message']['content'])現(xiàn)在,讓我們看看如何使用 ell 實(shí)現(xiàn)相同的結(jié)果:
import ell
@ell.simple(model="gpt-4o")
def hello(name: str):
"""You are a helpful assistant.""" # 系統(tǒng)提示
return f"Say hello to {name}!" # 用戶提示
greeting = hello("Sam Altman")
print(greeting)ell? 通過(guò)鼓勵(lì)你將提示定義為功能單元來(lái)簡(jiǎn)化提示。在這個(gè)示例中,hello 函數(shù)通過(guò)文檔字符串定義系統(tǒng)提示,通過(guò)返回字符串定義用戶提示。提示的用戶只需調(diào)用定義的函數(shù),而不需要手動(dòng)構(gòu)建消息。在此基礎(chǔ)上,我們可以進(jìn)一步地改進(jìn)提示。
import ell
import random
def get_random_adjective():
adjectives = ["enthusiastic", "cheerful", "warm", "friendly"]
return random.choice(adjectives)
@ell.simple(model="gpt-4o")
def hello(name: str):
"""You are a helpful assistant."""
adjective = get_random_adjective()
return f"Say a {adjective} hello to {name}!"
greeting = hello("Sam Altman")
print(greeting)在這個(gè)示例中,我們的 hello? LMP 依賴于 get_random_adjective? 函數(shù)。每次調(diào)用 hello? 時(shí),它都會(huì)生成一個(gè)不同的形容詞,創(chuàng)建動(dòng)態(tài)、多樣的提示。顯然,ell 可使提示更具可讀性、可維護(hù)性和可重用性。
提示工程是一個(gè)優(yōu)化過(guò)程
提示工程的過(guò)程類似于機(jī)器學(xué)習(xí)中的優(yōu)化過(guò)程,需要多次迭代。由于 LMP 只是函數(shù),ell 提供了豐富的工具來(lái)支持這一過(guò)程。

ell 通過(guò)靜態(tài)和動(dòng)態(tài)分析,提供了提示的自動(dòng)版本控制和序列化,并生成自動(dòng)提交消息到本地存儲(chǔ)。這一過(guò)程類似于機(jī)器學(xué)習(xí)訓(xùn)練中的檢查點(diǎn),但不需要特殊的 IDE 或編輯器——只需使用常規(guī)的 Python 代碼即可。
import ell
ell.init(store='./logdir') # 版本控制你的 LMP 和它們的調(diào)用
# 定義你的 LMP
hello("strawberry") # LMP 的源代碼和調(diào)用被保存到存儲(chǔ)中同時(shí),ell 提供了一個(gè)名為 Ell Studio 的本地開(kāi)源工具,可用于提示版本控制、監(jiān)控和可視化。通過(guò) Ell Studio,你可以將提示優(yōu)化過(guò)程科學(xué)化,并在問(wèn)題出現(xiàn)之前捕捉到回歸。
優(yōu)雅實(shí)現(xiàn)測(cè)試時(shí)計(jì)算
從演示到實(shí)際應(yīng)用,通常需要多次調(diào)用語(yǔ)言模型。這不僅僅是簡(jiǎn)單的字符串拼接,而是一個(gè)復(fù)雜的編程過(guò)程。通過(guò)強(qiáng)制功能分解問(wèn)題,ell 使得在可讀和模塊化的方式中實(shí)現(xiàn)測(cè)試時(shí)計(jì)算變得容易。

import ell
@ell.simple(model="gpt-4o-mini", temperature=1.0, n=10)
def write_ten_drafts(idea: str):
"""You are an adept story writer. The story should only be 3 paragraphs"""
return f"Write a story about {idea}."
@ell.simple(model="gpt-4o", temperature=0.1)
def choose_the_best_draft(drafts: List[str]):
"""You are an expert fiction editor."""
return f"Choose the best draft from the following list: {'\\n'.join(drafts)}."
drafts = write_ten_drafts(idea)
best_draft = choose_the_best_draft(drafts) # 從10個(gè)草稿中選擇最佳草稿測(cè)試時(shí)計(jì)算(Test-Time Computation)是機(jī)器學(xué)習(xí)和深度學(xué)習(xí)中的一個(gè)概念,指的是在模型推理階段(也就是測(cè)試時(shí))進(jìn)行額外的計(jì)算或處理,以提高模型的性能或適應(yīng)性。這種方法通常用于解決訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)之間存在差異的問(wèn)題,或者在不重新訓(xùn)練模型的情況下提高模型的泛化能力。其核心思路是不重新訓(xùn)練模型,而是在模型實(shí)際使用時(shí)進(jìn)行額外的處理,以提高模型的表現(xiàn)。類似于人類在應(yīng)用所學(xué)知識(shí)時(shí)會(huì)根據(jù)具體情況做出適當(dāng)靈活變通處理,而不是僵化執(zhí)行。
每次調(diào)用語(yǔ)言模型都很重要
每次調(diào)用語(yǔ)言模型都非常寶貴,值得跟蹤分析。在實(shí)踐中,LLM 調(diào)用用于微調(diào)、蒸餾、k-shot 提示、從人類反饋中進(jìn)行強(qiáng)化學(xué)習(xí)等。一個(gè)好的提示工程系統(tǒng)應(yīng)該將這些作為一等公民概念捕捉。

除了存儲(chǔ)每個(gè) LMP 的源代碼外,ell 還可以選擇性地本地保存每次調(diào)用語(yǔ)言模型的記錄。這使你能夠生成調(diào)用數(shù)據(jù)集,比較不同版本的 LMP 輸出,并充分利用提示工程的所有工件。
需要時(shí)復(fù)雜,不需要時(shí)簡(jiǎn)單
使用語(yǔ)言模型通常只是傳遞字符串,但有時(shí)需要更復(fù)雜的輸出。ell? 提供了 @ell.simple? 和 @ell.complex 裝飾器,分別用于生成簡(jiǎn)單字符串輸出和復(fù)雜的消息對(duì)象響應(yīng)。
import ell
@ell.tool()
def scrape_website(url: str):
return requests.get(url).text
@ell.complex(model="gpt-5-omni", tools=[scrape_website])
def get_news_story(topic: str):
return [
ell.system("""Use the web to find a news story about the topic"""),
ell.user(f"Find a news story about {topic}.")
]
message_response = get_news_story("stock market")
if message_response.tool_calls:
for tool_call in message_response.tool_calls:
# 處理工具調(diào)用
pass
if message_response.text:
print(message_response.text)
if message_response.audio:
# message_response.play_audio() 支持多模態(tài)輸出
pass多模態(tài)是一等公民
LLM 可以處理和生成各種類型的內(nèi)容,包括文本、圖像、音頻和視頻。使用這些數(shù)據(jù)類型進(jìn)行提示工程應(yīng)該像處理文本一樣簡(jiǎn)單。
from PIL import Image
import ell
@ell.simple(model="gpt-4o", temperature=0.1)
def describe_activity(image: Image.Image):
return [
ell.system("You are VisionGPT. Answer <5 words all lower case."),
ell.user(["Describe what the person in the image is doing:", image])
]
# 從攝像頭捕捉圖像
describe_activity(capture_webcam_image()) # 輸出: "they are holding a book"
ell? 支持多模態(tài)輸入和輸出的豐富類型轉(zhuǎn)換。你可以在 LMP 返回的 Message 對(duì)象中內(nèi)聯(lián)使用 PIL 圖像、音頻和其他多模態(tài)輸入。
提示工程庫(kù)不干擾你的工作流程
ell 設(shè)計(jì)為一個(gè)輕量級(jí)且不干擾的庫(kù)。它不要求你改變編碼風(fēng)格或使用特殊的編輯器。

你可以繼續(xù)在你的 IDE 中使用常規(guī)的 Python 代碼來(lái)定義和修改提示,同時(shí)利用 ell? 的功能來(lái)可視化和分析你的提示。你可以逐步從 langchain 遷移到 ell,一次一個(gè)函數(shù)。
結(jié)語(yǔ)
ell? 通過(guò)將提示視為函數(shù),并提供一系列強(qiáng)大的工具,重新定義了提示工程。它不僅簡(jiǎn)化了提示的創(chuàng)建和管理過(guò)程,還使得提示優(yōu)化變得科學(xué)化和系統(tǒng)化。無(wú)論你是提示工程的新手還是經(jīng)驗(yàn)豐富的專家,ell 都能為你提供有價(jià)值的支持。
參考資料
[1]ell: https://docs.ell.so/
本文轉(zhuǎn)載自 ??AI工程化??,作者: ully

















