重點摘要
- 使用 ChatOpenAI,將 base_url 設為 API 並設定模型為 uncensored。
- 鏈、串流輸出、函式呼叫與 JSON 輸出皆透過標準聊天完成路由進行。
- 完整金鑰將批次並行請求上限設為 8,試用金鑰設為 2,以避免 429 錯誤。
- 這是單一託管模型,並非路由器,因此沒有跨供應商模型切換功能。
簡短設定
常見的langchain + llm問題是,是否需要為第三方端點進行特殊整合。你不需要。LangChain 的 OpenAI 聊天包裝器接受自訂 Base URL,且此 API 遵循 OpenAI 聊天補全格式,因此標準類別即可運作。安裝套件,傳入三個值,你就能獲得一個聊天模型物件,可將其放入任何鏈中。
pip install -U langchain-openai langchain-core
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.nsfwllmrouter.com/v1",
api_key="YOUR_API_KEY",
temperature=0.7,
)
print(llm.invoke("Give me one sentence about LangChain.").content)
從 API 金鑰頁面取得金鑰。新用戶註冊後可一鍵領取 $0.50 的免費試用額度,足以多次運行本文中的所有內容。模型 ID 始終為 uncensored,請求會發送至 POST /v1/chat/completions。
關於網站名稱的說明:儘管網域名稱中包含 "router" 字樣,但這是獨立供應商運營的單一開放權重模型,並非跨供應商的路由器,也不是任何供應商的官方 API。在此無法選擇不同模型。你的程式碼指定一個模型,該模型即會回應。
將金鑰排除在原始碼之外
硬編碼金鑰適合首次測試,但首次提交檔案時就會成為問題。請從環境變數讀取。LangChain 包裝的 OpenAI 客戶端庫預設會尋找 OPENAI_API_KEY 與 OPENAI_BASE_URL,因此你可以在殼層中設定它們,並以更少的參數建構模型。
export OPENAI_API_KEY="YOUR_API_KEY"
export OPENAI_BASE_URL="https://api.nsfwllmrouter.com/v1"
import os
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="uncensored",
base_url=os.environ.get("OPENAI_BASE_URL", "https://api.nsfwllmrouter.com/v1"),
api_key=os.environ["OPENAI_API_KEY"],
)
如上所述明確傳遞 base URL 有一個優勢。如果同一台機器上的另一個專案使用真正的 OpenAI 服務並依賴相同的環境變數,你的明確參數可防止兩者衝突。
帶有提示詞模板的第一個鏈
大多數實際工作使用提示詞模板、模型與輸出解析器,並透過管道運算子連接。這是 LangChain 表達語言風格,對於自訂端點不需要任何特殊設定。
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.nsfwllmrouter.com/v1",
api_key="YOUR_API_KEY",
)
prompt = ChatPromptTemplate.from_messages([
("system", "You write short story openings in the style the user asks for."),
("human", "Genre: {genre}\nSetting: {setting}\nWrite three sentences."),
])
chain = prompt | llm | StrOutputParser()
print(chain.invoke({"genre": "noir mystery", "setting": "a rainy harbor town"}))
該模型對合法成人用途無內容審查,這在鏈生成小說、角色扮演場景或伴侶對話時很重要,因為更謹慎的模型可能會拒絕這些內容。唯一的固定規則是絕不會產生涉及未成年人的性內容。如果你的產品有更嚴格的規則,請在此之上建立自己的輸入驗證。
串流輸出與用量
API 支援透過 stream: true 進行伺服器發送事件串流輸出,且用量會在串流結束時報告。在 LangChain 中,你呼叫 .stream() 並遍歷區塊。
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.nsfwllmrouter.com/v1",
api_key="YOUR_API_KEY",
)
for chunk in llm.stream("Write a four-line poem about debugging at night."):
print(chunk.content, end="", flush=True)
一個需要注意的細節:串流請求會佔用一個並行請求槽位,直到串流結束。如果你的 UI 開啟串流但使用者未關閉就離開,該槽位仍會保持忙碌。完整金鑰允許 8 個並行請求,因此少數遺棄的串流可能會阻塞新請求。當客戶端斷開連接時,請取消迭代器。
函式呼叫和代理
支援工具呼叫:你傳入 tools 並可選傳入 tool_choice,模型會以 tool_calls 回覆(也可串流輸出),然後你以 role: "tool" 將結果作為訊息傳回。在 LangChain 中,bind_tools 會為你處理線路格式。
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
@tool
def word_count(text: str) -> int:
'Count the words in a piece of text.'
return len(text.split())
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.nsfwllmrouter.com/v1",
api_key="YOUR_API_KEY",
)
llm_with_tools = llm.bind_tools([word_count])
msg = llm_with_tools.invoke("How many words are in: the quick brown fox?")
for call in msg.tool_calls:
print(call["name"], call["args"], word_count.invoke(call["args"]))
對於完整的代理程式迴圈,LangChain 的代理程式輔助工具或 LangGraph 會為你執行此迴圈:呼叫模型、執行請求的工具、附加工具訊息、再次呼叫。工具使用遵循標準 OpenAI 格式,因此你為任何相容端點編寫的程式碼同樣適用。與任何開放權重模型一樣,請測試你的特定工具架構。保持參數名稱簡潔、描述簡短,並將工具列表保持較小,因為長列表會讓較弱的模型有更多空間選錯。
使用 JSON 模式的結構化輸出
JSON 模式透過 response_format: {"type": "json_object"} 提供。在 LangChain 中,你可以將其作為模型參數傳入並自行解析結果,這讓你能控制驗證與重試。
import json
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.nsfwllmrouter.com/v1",
api_key="YOUR_API_KEY",
model_kwargs={"response_format": {"type": "json_object"}},
)
msg = llm.invoke(
"Return a JSON object with keys title and tags (a list of three strings) "
"for an article about hiking."
)
data = json.loads(msg.content)
print(data["title"], data["tags"])
在提示詞中提及 "JSON" 並描述你需要的鍵。JSON 模式會使輸出為有效的 JSON,但不保證符合你的特定架構,因此解析後請檢查鍵,並在失敗時重試。由於失敗請求不會計費,針對格式錯誤輸出的重試迴圈成本很低。
並行請求、重試與速率限制
LangChain 透過 .batch() 輕鬆實現工作分發,這也是大多數人遇到第一個速率限制的地方。完整金鑰允許 8 個並行請求與每分鐘 300 個請求。試用金鑰允許 2 個並行請求與每分鐘 60 個請求。超過限制時,API 會回覆 HTTP 429。超過每分鐘請求數時錯誤碼為 rate_limited,同時請求過多時錯誤碼為 concurrency。在暫時過載時,你也會收到帶有 Retry-After: 5 標頭的 429。
自行設定批次並行請求數,並讓客戶端以指數退避方式重試:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.nsfwllmrouter.com/v1",
api_key="YOUR_API_KEY",
max_retries=4,
timeout=120,
)
inputs = [f"Summarize idea number {i} in one line." for i in range(40)]
results = llm.batch(inputs, config={"max_concurrency": 6})
print(len(results))
在完整金鑰上保持 6 個請求可為帳戶的其他請求保留緩衝空間。試用金鑰請使用 2。如果你仍看到 concurrency 錯誤,請尋找從未結束的串流,因為每個串流都會佔用一個槽位。每個回應都帶有 X-Request-Id,這是聯繫支援時應引用的值,以及 X-Balance-USD,顯示你的剩餘預付額度。
網頁應用程式的異步呼叫
在網頁伺服器中,你通常不希望使用阻塞呼叫。每個 LangChain 聊天模型都有其方法的異步版本,分別命名為 ainvoke、astream 與 abatch,它們對此端點的運作方式與同步版本相同。
import asyncio
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.nsfwllmrouter.com/v1",
api_key="YOUR_API_KEY",
)
async def main():
async for chunk in llm.astream("Describe a quiet harbor at dawn in two sentences."):
print(chunk.content, end="", flush=True)
asyncio.run(main())
在異步服務中,請使用以你的金鑰大小為基礎的訊號量來保護進行中的呼叫數量,例如完整金鑰設為 8。這可防止你自己的應用程式的一個忙碌端點佔滿所有槽位並導致其他端點飢渴。在呼叫周圍捕獲異常,若有 X-Request-Id 標頭請記錄下來,並向使用者顯示簡短的重試訊息而非堆疊追蹤。
除錯提示:如果鏈的行為異常,請列印模型收到的確切訊息。提示詞模板有時會插入額外的空白或遺失變數,而模型只能回答它收到的內容。LangChain 的 verbose 與 debug 開關,或 LangSmith 追蹤(如果你已使用它),會顯示最終訊息列表。
上下文視窗對鏈的影響
上下文視窗為 100,000 token,包含提示詞與完成內容,且 max_tokens 是可選的。這足夠用於將許多文件放入單一提示詞的檢索鏈,或保留長歷史記錄的對話記憶。但如果每次輪次都重新發送完整歷史記錄而不進行修剪,也會變得昂貴。
快速計算。一個檢索步驟發送 12,000 個輸入 token 並取得 800 個輸出,成本為 0.012 x $0.15 + 0.0008 x $0.50 = $0.0018 + $0.0004 = $0.0022。執行 1,000 次,你需支付 $2.20。定價為每 1M 輸入 token $0.15,每 1M 輸出 token $0.50,無訂閱費,你只需為鏈實際使用的部分付費。定價頁面提供儲值選項,快速入門文件列出所有支援的參數。提示詞不會用於訓練。
