用開發(fā):從黑盒調(diào)用到工程化實(shí)踐的架構(gòu)優(yōu)化指南)
如果你正在開發(fā)或使用基于大語言模型LLM的應(yīng)用是否遇到過這些情況模型輸出看似流暢但內(nèi)容空洞、邏輯混亂甚至包含事實(shí)性錯(cuò)誤應(yīng)用響應(yīng)時(shí)快時(shí)慢成本難以控制或者你精心設(shè)計(jì)的提示詞Prompt在某個(gè)模型上效果拔群換一個(gè)模型就完全失效這很可能不是模型本身的問題而是陷入了“不健康”的 LLM 使用模式。這種模式遠(yuǎn)比我們想象中更普遍它消耗著開發(fā)者的精力侵蝕著項(xiàng)目的穩(wěn)定性和用戶體驗(yàn)最終導(dǎo)致項(xiàng)目難以維護(hù)和迭代。很多人將 LLM 視為一個(gè)“黑盒”API只關(guān)心輸入和輸出卻忽略了中間至關(guān)重要的工程化實(shí)踐。本文將深入剖析 LLM 應(yīng)用開發(fā)中那些常見卻容易被忽視的“不健康”實(shí)踐。我們不會(huì)停留在“要寫好提示詞”這種泛泛之談而是會(huì)深入到架構(gòu)設(shè)計(jì)、工程流程、成本控制和效果評(píng)估等具體層面。通過對(duì)比“不健康”與“健康”的實(shí)踐差異并提供可落地的代碼示例與最佳實(shí)踐幫助你構(gòu)建出更健壯、更高效、更可控的 LLM 應(yīng)用。1. 這篇文章真正要解決的問題為什么你的LLM應(yīng)用總在“帶病運(yùn)行”許多開發(fā)者在初次接觸 LLM 時(shí)容易陷入一個(gè)誤區(qū)認(rèn)為調(diào)用一個(gè)強(qiáng)大的模型 API就能解決所有問題。這種“一招鮮”的思維是“不健康”使用的根源。它導(dǎo)致了一系列典型癥狀“提示詞煉金術(shù)”花費(fèi)大量時(shí)間反復(fù)微調(diào)一個(gè)巨型提示詞試圖讓它解決所有邊界情況結(jié)果提示詞變得冗長(zhǎng)、難以維護(hù)且對(duì)模型版本極度敏感。“黑盒依賴癥”將核心業(yè)務(wù)邏輯完全寄托于單一模型的單次響應(yīng)上沒有校驗(yàn)、沒有備選、沒有降級(jí)策略一旦模型“胡言亂語”或服務(wù)不可用整個(gè)應(yīng)用隨之崩潰。“成本失控”忽視 Token 消耗頻繁調(diào)用大模型處理簡(jiǎn)單任務(wù)或者使用高成本模型完成低價(jià)值工作導(dǎo)致賬單激增。“效果玄學(xué)”缺乏客觀的評(píng)估指標(biāo)和測(cè)試集僅憑“感覺”判斷模型輸出好壞迭代優(yōu)化沒有依據(jù)陷入主觀爭(zhēng)論。這些問題背后反映的是將 LLM 當(dāng)作“魔法”而非“工程組件”的認(rèn)知偏差。健康的 LLM 應(yīng)用開發(fā)應(yīng)該像構(gòu)建任何分布式系統(tǒng)一樣關(guān)注可靠性、可觀測(cè)性、成本效率和可迭代性。本文的目標(biāo)就是幫你建立這套工程化思維將 LLM 從“黑盒魔法”轉(zhuǎn)變?yōu)椤翱煽氐墓こ探M件”。2. 核心概念從“魔法調(diào)用”到“工程化組件”要理解如何健康使用 LLM首先需要明確幾個(gè)關(guān)鍵概念及其在工程中的角色。LLM (大語言模型)本文的核心。它本質(zhì)上是一個(gè)基于海量數(shù)據(jù)訓(xùn)練的概率模型根據(jù)輸入序列預(yù)測(cè)下一個(gè) token。在工程中它應(yīng)被視為一個(gè)具有不確定性的計(jì)算單元而非確定性的函數(shù)。Agent (智能體)一個(gè)能感知環(huán)境、進(jìn)行決策并執(zhí)行動(dòng)作以完成目標(biāo)的系統(tǒng)。在 LLM 應(yīng)用中Agent 通常以 LLM 作為“大腦”結(jié)合工具Tools、記憶Memory和規(guī)劃Planning來完成任務(wù)。健康的 Agent 設(shè)計(jì)強(qiáng)調(diào)任務(wù)分解、工具調(diào)用和過程可控。RAG (檢索增強(qiáng)生成)為了解決模型知識(shí)陳舊和幻覺問題通過從外部知識(shí)庫檢索相關(guān)信息并將其作為上下文提供給 LLM從而生成更準(zhǔn)確、更相關(guān)的回答。健康的 RAG 系統(tǒng)核心在于高質(zhì)量的檢索、精準(zhǔn)的相關(guān)性過濾和有效的上下文組織。Fine-tuning (微調(diào))在特定領(lǐng)域數(shù)據(jù)上繼續(xù)訓(xùn)練預(yù)訓(xùn)練模型使其適應(yīng)特定任務(wù)或風(fēng)格。它不同于提示工程是改變模型自身的參數(shù)。健康的使用場(chǎng)景是當(dāng)你有大量高質(zhì)量、結(jié)構(gòu)化的領(lǐng)域數(shù)據(jù)且需要模型深層次掌握特定模式或術(shù)語時(shí)。Prompt Engineering (提示工程)通過精心設(shè)計(jì)輸入文本來引導(dǎo)模型產(chǎn)生期望的輸出。健康的提示工程是結(jié)構(gòu)化、可復(fù)用、可測(cè)試的而不是一次性的“咒語”。一個(gè)常見的架構(gòu)層級(jí)誤解是認(rèn)為 LLM、Agent、RAG、Fine-tuning 是并列或遞進(jìn)的技術(shù)選型。實(shí)際上它們更像是構(gòu)建 AI 應(yīng)用的不同工具層和策略層可以組合使用。一個(gè)復(fù)雜的 AI 應(yīng)用可能同時(shí)包含基于微調(diào)模型的核心理解能力LLM、通過 RAG 接入最新知識(shí)、并由一個(gè) Agent 框架來協(xié)調(diào)多步驟任務(wù)執(zhí)行。3. 環(huán)境準(zhǔn)備構(gòu)建可測(cè)試的LLM應(yīng)用基礎(chǔ)在開始優(yōu)化實(shí)踐前我們需要一個(gè)基礎(chǔ)的、可運(yùn)行的環(huán)境來進(jìn)行演示。這里我們選擇 Python 和 LangChain 框架因?yàn)樗峁┝素S富的抽象能清晰展示問題與解決方案。請(qǐng)注意以下版本為示例請(qǐng)根據(jù)你的實(shí)際環(huán)境調(diào)整。基礎(chǔ)環(huán)境Python 3.9pip 包管理工具安裝核心依賴我們將安裝 LangChain 及其 OpenAI 集成用于調(diào)用模型以及用于評(píng)估的langchain-community和測(cè)試工具pytest。# 創(chuàng)建并進(jìn)入項(xiàng)目目錄 mkdir healthy-llm-app cd healthy-llm-app python -m venv venv # Windows: venv\Scripts\activate # Linux/Mac: source venv/bin/activate # 安裝依賴 pip install langchain langchain-openai langchain-community pytest pip install python-dotenv # 用于管理環(huán)境變量配置模型API密鑰創(chuàng)建一個(gè).env文件來安全存儲(chǔ)你的 API 密鑰切勿提交到代碼倉庫。# .env 文件內(nèi)容 OPENAI_API_KEY你的-openai-api-key # 或其他模型的API_KEY如 ANTHROPIC_API_KEY, GROQ_API_KEY 等在代碼中通過dotenv加載# config.py import os from dotenv import load_dotenv load_dotenv() OPENAI_API_KEY os.getenv(OPENAI_API_KEY)4. 癥狀一脆弱的長(zhǎng)提示詞與“提示詞工程”不健康的實(shí)踐將所有邏輯和約束都塞進(jìn)一個(gè)龐大的系統(tǒng)提示詞System Prompt中。例如一個(gè)試圖讓模型扮演客服并處理各種情況的提示詞可能長(zhǎng)達(dá)數(shù)百字包含大量“如果...那么...”的規(guī)則。# unhealthy_prompt.py - 不健康的“巨無霸”提示詞示例 unhealthy_system_prompt 你是一個(gè)專業(yè)的、友好的、高效的AI客服助手名叫“智助”。你的目標(biāo)是解決用戶關(guān)于產(chǎn)品A、產(chǎn)品B和訂閱服務(wù)的問題。 你必須始終使用中文回復(fù)。你必須先問候用戶。如果用戶問題關(guān)于產(chǎn)品A請(qǐng)介紹其核心功能X, Y, Z。如果關(guān)于產(chǎn)品B請(qǐng)強(qiáng)調(diào)其優(yōu)勢(shì)輕便、續(xù)航長(zhǎng)。 如果用戶表達(dá)不滿你必須先道歉。如果用戶詢問價(jià)格請(qǐng)引導(dǎo)他們查看官網(wǎng)定價(jià)頁面切勿直接報(bào)價(jià)。如果用戶要求轉(zhuǎn)人工請(qǐng)告知工作時(shí)間是工作日9-18點(diǎn)。 如果用戶問題超出你的知識(shí)范圍請(qǐng)如實(shí)告知并建議通過郵件聯(lián)系 supportexample.com。記住絕對(duì)不能創(chuàng)造不存在的信息。 現(xiàn)在請(qǐng)開始與用戶對(duì)話。 # 然后直接將這個(gè)長(zhǎng)提示詞發(fā)給模型...問題這種提示詞難以維護(hù)、調(diào)試且模型可能無法完全遵循所有指令指令淹沒。更糟糕的是它混合了角色定義、業(yè)務(wù)邏輯、流程控制和內(nèi)容規(guī)范任何改動(dòng)都可能產(chǎn)生意想不到的副作用。健康的實(shí)踐結(jié)構(gòu)化提示與鏈?zhǔn)秸{(diào)用。將復(fù)雜的任務(wù)分解為多個(gè)步驟每個(gè)步驟使用一個(gè)簡(jiǎn)潔、目標(biāo)明確的提示詞并通過鏈Chain組合起來。# healthy_chain.py - 使用LangChain Expression Language (LCEL) 構(gòu)建健康的工作流 from langchain.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_openai import ChatOpenAI from config import OPENAI_API_KEY # 1. 定義角色和基礎(chǔ)行為的系統(tǒng)提示詞保持穩(wěn)定 system_prompt_base ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template(你是一個(gè)專業(yè)的AI客服助手名叫‘智助’。請(qǐng)用中文友好、清晰地回應(yīng)用戶。), ]) # 2. 定義分類用戶意圖的提示詞 classify_intent_prompt ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template(請(qǐng)分析用戶的輸入判斷其意圖類別。只輸出以下類別之一產(chǎn)品咨詢、投訴建議、轉(zhuǎn)人工請(qǐng)求、其他。), HumanMessagePromptTemplate.from_template(用戶輸入{user_input}) ]) # 3. 定義處理產(chǎn)品咨詢的專用提示詞 product_qa_prompt ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template(你負(fù)責(zé)解答關(guān)于{product_name}的咨詢。請(qǐng)根據(jù)已知信息回答{product_info}。如果無法回答請(qǐng)建議用戶查閱官網(wǎng)或聯(lián)系客服。), HumanMessagePromptTemplate.from_template(用戶問題{user_question}) ]) # 初始化模型 llm ChatOpenAI(modelgpt-3.5-turbo, api_keyOPENAI_API_KEY, temperature0) output_parser StrOutputParser() # 構(gòu)建鏈1. 分類意圖 - 2. 根據(jù)意圖路由到不同處理邏輯 from langchain.schema.runnable import RunnableBranch, RunnableLambda def route_by_intent(data): intent data[intent] user_input data[user_input] if 產(chǎn)品咨詢 in intent: # 這里可以進(jìn)一步解析是哪個(gè)產(chǎn)品簡(jiǎn)化示例直接使用產(chǎn)品A return product_qa_prompt | llm | output_parser elif 轉(zhuǎn)人工請(qǐng)求 in intent: return RunnableLambda(lambda x: 我們的工作時(shí)間是工作日9-18點(diǎn)。您可以稍后再試或發(fā)送郵件至 supportexample.com。) else: # 默認(rèn)回復(fù)鏈 default_chain system_prompt_base HumanMessagePromptTemplate.from_template({user_input}) return default_chain | llm | output_parser # 主處理鏈 full_chain { intent: classify_intent_prompt | llm | output_parser, user_input: lambda x: x[user_input] } | RunnableBranch( (lambda x: 產(chǎn)品咨詢 in x[intent], route_by_intent), (lambda x: 轉(zhuǎn)人工請(qǐng)求 in x[intent], route_by_intent), route_by_intent # 默認(rèn)分支 ) # 測(cè)試 if __name__ __main__: test_input {user_input: 我想了解一下產(chǎn)品A有什么功能} result full_chain.invoke(test_input) print(健康鏈?zhǔn)教幚斫Y(jié)果, result)優(yōu)勢(shì)每個(gè)提示詞職責(zé)單一易于測(cè)試和優(yōu)化。工作流清晰可見可以方便地添加日志、監(jiān)控或修改單個(gè)步驟。例如可以單獨(dú)測(cè)試classify_intent_prompt的準(zhǔn)確率。5. 癥狀二忽視幻覺與缺乏事實(shí)核查不健康的實(shí)踐無條件信任模型的每一次輸出尤其是當(dāng)它聽起來很自信的時(shí)候。直接將模型生成的內(nèi)容展示給用戶或用于后續(xù)決策。健康的實(shí)踐為模型輸出增加“護(hù)欄”。至少包含以下一層或多層防護(hù)輸出結(jié)構(gòu)化要求模型以 JSON、XML 等指定格式輸出便于程序化解析和驗(yàn)證。后處理校驗(yàn)對(duì)關(guān)鍵信息如日期、金額、人名進(jìn)行正則表達(dá)式或規(guī)則校驗(yàn)。事實(shí)溯源對(duì)于知識(shí)性問題強(qiáng)制要求模型提供引用來源如在 RAG 中返回檢索到的文檔片段。置信度提示讓模型對(duì)自己回答的確定性進(jìn)行評(píng)分。# hallucination_guard.py - 為輸出增加結(jié)構(gòu)化約束和校驗(yàn) from langchain.output_parsers import PydanticOutputParser from pydantic import BaseModel, Field, validator from typing import Optional from datetime import datetime # 1. 使用Pydantic定義期望的輸出結(jié)構(gòu) class FactualResponse(BaseModel): 期望模型返回的結(jié)構(gòu)化答案 answer: str Field(description對(duì)用戶問題的直接回答) confidence: float Field(description對(duì)此答案的確信度0到1之間, ge0, le1) supporting_facts: Optional[list[str]] Field(description支持此答案的關(guān)鍵事實(shí)列表如果沒有則為空列表, default_factorylist) cannot_answer: bool Field(description如果問題超出知識(shí)范圍或無法確認(rèn)請(qǐng)?jiān)O(shè)為True, defaultFalse) validator(confidence) def confidence_range(cls, v): if not 0 v 1: raise ValueError(置信度必須在0到1之間) return v # 2. 創(chuàng)建帶有輸出解析器的提示詞 parser PydanticOutputParser(pydantic_objectFactualResponse) guardrail_prompt ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template( 你是一個(gè)嚴(yán)謹(jǐn)?shù)膯柎鹬帧U?qǐng)基于已知信息回答用戶問題。 如果你不確定或信息不足請(qǐng)務(wù)必承認(rèn)。 你必須嚴(yán)格按照以下格式輸出\n{format_instructions} ), HumanMessagePromptTemplate.from_template(問題{question}\n已知信息{context}) ]) # 3. 構(gòu)建鏈 guarded_chain guardrail_prompt | llm | parser # 4. 模擬已知信息上下文在實(shí)際RAG中這里來自向量檢索 simulated_context 特斯拉Model 3于2017年開始交付其最長(zhǎng)續(xù)航版本EPA標(biāo)準(zhǔn)里程約為358英里約576公里。 # 5. 測(cè)試 try: result: FactualResponse guarded_chain.invoke({ question: 特斯拉Model 3的續(xù)航里程是多少, context: simulated_context, format_instructions: parser.get_format_instructions() }) print(f答案{result.answer}) print(f置信度{result.confidence}) print(f支持事實(shí){result.supporting_facts}) print(f無法回答{result.cannot_answer}) # 6. 后處理校驗(yàn)例如如果置信度低于閾值則觸發(fā)人工審核或降級(jí)回答 if result.confidence 0.7: print(警告模型回答置信度較低建議人工復(fù)核。) # 可以在這里觸發(fā)備用回答邏輯例如返回一個(gè)更保守的答案 except Exception as e: print(f解析模型輸出失敗{e}) # 這里可以執(zhí)行降級(jí)策略例如返回一個(gè)默認(rèn)錯(cuò)誤信息或調(diào)用更簡(jiǎn)單的模型通過這種方式我們將模型的自由文本輸出約束到了一個(gè)可程序化校驗(yàn)的框架內(nèi)并引入了“置信度”這一元信息為后續(xù)的決策流程如人工審核提供了依據(jù)。6. 癥狀三成本黑洞與低效調(diào)用不健康的實(shí)踐盲目使用最大、最貴的模型處理所有請(qǐng)求頻繁進(jìn)行無意義的重復(fù)調(diào)用在鏈?zhǔn)秸{(diào)用中上游的小錯(cuò)誤導(dǎo)致下游昂貴的模型調(diào)用被浪費(fèi)。健康的實(shí)踐實(shí)施成本感知的調(diào)用策略。模型路由根據(jù)任務(wù)復(fù)雜度選擇模型。簡(jiǎn)單分類、提取任務(wù)使用小型/快速模型如gpt-3.5-turbo復(fù)雜創(chuàng)作、推理任務(wù)使用大型模型如gpt-4。緩存對(duì)相同或相似的提示詞結(jié)果進(jìn)行緩存避免重復(fù)計(jì)算。節(jié)流與重試優(yōu)雅處理速率限制如錯(cuò)誤碼 429實(shí)現(xiàn)指數(shù)退避重試。預(yù)算監(jiān)控與告警在應(yīng)用層面集成成本監(jiān)控。# cost_aware_chain.py - 實(shí)現(xiàn)模型路由和緩存 from langchain.cache import InMemoryCache from langchain.globals import set_llm_cache from langchain_openai import ChatOpenAI import time # 1. 啟用緩存生產(chǎn)環(huán)境應(yīng)使用Redis等分布式緩存 set_llm_cache(InMemoryCache()) # 2. 初始化不同成本和能力的模型 fast_llm ChatOpenAI(modelgpt-3.5-turbo, api_keyOPENAI_API_KEY, temperature0, max_tokens500) powerful_llm ChatOpenAI(modelgpt-4, api_keyOPENAI_API_KEY, temperature0.2, max_tokens1000) # 3. 定義一個(gè)路由函數(shù)根據(jù)輸入決定使用哪個(gè)模型 def route_model(user_input: str) - ChatOpenAI: 簡(jiǎn)單的路由邏輯如果問題短且是簡(jiǎn)單問答用快模型否則用強(qiáng)模型 if len(user_input.split()) 10 and ? in user_input: print(f[路由] 使用快速模型處理{user_input[:50]}...) return fast_llm else: print(f[路由] 使用強(qiáng)大模型處理{user_input[:50]}...) return powerful_llm # 4. 構(gòu)建一個(gè)帶有路由和緩存的鏈 from langchain.schema.runnable import RunnableLambda def model_router(input_dict): chosen_model route_model(input_dict[question]) # 將模型作為可調(diào)用對(duì)象嵌入鏈中 return chosen_model routed_chain ( RunnableLambda(lambda x: {question: x}) # 包裝輸入 | RunnableLambda(model_router) # 路由到具體模型 | StrOutputParser() ) # 5. 測(cè)試緩存效果 print(第一次調(diào)用無緩存) start time.time() result1 routed_chain.invoke(中國(guó)的首都是哪里) print(f結(jié)果{result1}, 耗時(shí){time.time()-start:.2f}秒) print(\n第二次調(diào)用相同問題應(yīng)有緩存) start time.time() result2 routed_chain.invoke(中國(guó)的首都是哪里) print(f結(jié)果{result2}, 耗時(shí){time.time()-start:.2f}秒) # 6. 模擬處理429錯(cuò)誤節(jié)流的包裝函數(shù) from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type import openai retry( stopstop_after_attempt(3), waitwait_exponential(multiplier1, min2, max10), retryretry_if_exception_type(openai.RateLimitError) ) def robust_llm_call(chain, input_text): 一個(gè)帶有重試機(jī)制的LLM調(diào)用包裝器 try: return chain.invoke(input_text) except openai.RateLimitError as e: print(f遇到速率限制正在重試... 錯(cuò)誤{e}) raise e # tenacity會(huì)捕獲并重試 except Exception as e: print(f調(diào)用發(fā)生其他錯(cuò)誤{e}) return 服務(wù)暫時(shí)不可用請(qǐng)稍后再試。這個(gè)示例展示了如何通過簡(jiǎn)單的規(guī)則進(jìn)行模型路由利用緩存避免重復(fù)開銷以及使用tenacity庫實(shí)現(xiàn)健壯的重試邏輯。在生產(chǎn)環(huán)境中路由邏輯可以更復(fù)雜基于歷史性能、當(dāng)前負(fù)載和成本預(yù)算進(jìn)行動(dòng)態(tài)決策。7. 癥狀四不可觀測(cè)與難以調(diào)試不健康的實(shí)踐將 LLM 調(diào)用視為普通函數(shù)調(diào)用除了輸入輸出沒有記錄任何中間狀態(tài)、Token 消耗、延遲或模型內(nèi)部的思考過程如果支持。健康的實(shí)踐全面日志記錄與鏈路追蹤。記錄每一次調(diào)用的詳細(xì)信息為調(diào)試和優(yōu)化提供數(shù)據(jù)支持。LangChain 提供了callbacks機(jī)制來方便地集成日志。# logging_and_tracing.py - 集成日志和追蹤 import logging from langchain.callbacks.tracers import ConsoleCallbackHandler from langchain.callbacks import FileCallbackHandler from datetime import datetime # 1. 配置日志 log_file fllm_app_{datetime.now().strftime(%Y%m%d)}.log logging.basicConfig(levellogging.INFO, format%(asctime)s - %(name)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(log_file), logging.StreamHandler() ]) logger logging.getLogger(__name__) # 2. 自定義回調(diào)處理器記錄關(guān)鍵信息 class MetricsCallbackHandler(FileCallbackHandler): def on_llm_end(self, response, **kwargs): # 記錄Token使用情況如果響應(yīng)中包含 if hasattr(response, llm_output) and response.llm_output and token_usage in response.llm_output: usage response.llm_output[token_usage] logger.info(fLLM調(diào)用結(jié)束 - 模型: {kwargs.get(model_name, N/A)}, fPrompt Tokens: {usage.get(prompt_tokens)}, fCompletion Tokens: {usage.get(completion_tokens)}, fTotal Tokens: {usage.get(total_tokens)}) # 記錄輸入和輸出注意脫敏 logger.info(f輸入長(zhǎng)度: {len(str(kwargs.get(prompts, [])))} 字符) logger.info(f輸出: {str(response.generations[0][0].text)[:200]}...) # 只記錄前200字符 # 3. 在鏈的調(diào)用中傳入回調(diào)處理器 callbacks [ConsoleCallbackHandler(), MetricsCallbackHandler(log_file)] # 使用之前定義的 guarded_chain并傳入callbacks try: traced_result guarded_chain.invoke({ question: 特斯拉Model 3的續(xù)航里程是多少, context: simulated_context, format_instructions: parser.get_format_instructions() }, config{callbacks: callbacks}) except Exception as e: logger.error(f鏈?zhǔn)秸{(diào)用失敗: {e}) # 4. 更高級(jí)的集成使用 LangSmith (LangChain官方平臺(tái)) 進(jìn)行可視化追蹤 # 需要設(shè)置環(huán)境變量 LANGCHAIN_TRACING_V2true 和 LANGCHAIN_API_KEY # 設(shè)置后所有鏈的調(diào)用將自動(dòng)記錄到LangSmith可以查看詳細(xì)的執(zhí)行流程、耗時(shí)和中間結(jié)果。通過系統(tǒng)化的日志記錄你可以分析哪些提示詞最消耗 Token哪個(gè)處理步驟最慢模型的回答質(zhì)量如何隨時(shí)間變化這些數(shù)據(jù)是進(jìn)行性能優(yōu)化和成本控制的基礎(chǔ)。8. 常見問題與排查思路在開發(fā)和運(yùn)維 LLM 應(yīng)用時(shí)你會(huì)遇到各種問題。下表列出了一些典型問題及其排查路徑問題現(xiàn)象可能原因排查方式解決方案模型輸出完全無關(guān)或混亂1. 提示詞指令不清晰或矛盾。2. 上下文過長(zhǎng)導(dǎo)致關(guān)鍵指令被淹沒。3. 模型溫度temperature參數(shù)過高。1. 檢查并簡(jiǎn)化系統(tǒng)提示詞。2. 查看實(shí)際發(fā)送的完整 Prompt。3. 將 temperature 暫時(shí)設(shè)為0進(jìn)行測(cè)試。1. 采用結(jié)構(gòu)化、分步驟的提示詞。2. 對(duì)長(zhǎng)上下文進(jìn)行摘要或關(guān)鍵信息提取。3. 調(diào)整 temperature 至 0-0.3 以獲得更確定性輸出。應(yīng)用響應(yīng)速度極慢1. 網(wǎng)絡(luò)延遲或模型服務(wù)端延遲。2. 使用了不必要的大模型處理簡(jiǎn)單任務(wù)。3. 鏈?zhǔn)秸{(diào)用中存在串行阻塞。1. 記錄每個(gè)LLM調(diào)用的耗時(shí)。2. 分析任務(wù)復(fù)雜度與模型選型是否匹配。3. 檢查是否有可以并行化的步驟。1. 為模型調(diào)用設(shè)置合理的超時(shí)時(shí)間。2. 實(shí)施模型路由小任務(wù)用小模型。3. 使用RunnableParallel并行執(zhí)行獨(dú)立步驟。Token 消耗遠(yuǎn)超預(yù)期1. 提示詞中包含大量冗余信息。2. 重復(fù)調(diào)用相同或相似提示詞。3. 輸出長(zhǎng)度設(shè)置max_tokens過大。1. 審查提示詞模板移除不必要的描述。2. 檢查緩存是否生效。3. 統(tǒng)計(jì)輸入輸出的平均 Token 數(shù)。1. 優(yōu)化提示詞使用更簡(jiǎn)潔的指令。2. 確保緩存機(jī)制正確啟用。3. 根據(jù)任務(wù)合理設(shè)置max_tokens對(duì)長(zhǎng)輸出進(jìn)行分塊。遇到429 Rate Limit錯(cuò)誤1. 短時(shí)間內(nèi)請(qǐng)求頻率超過供應(yīng)商限制。2. 多進(jìn)程/多實(shí)例共享同一個(gè)API密鑰。1. 查看錯(cuò)誤信息中的限制詳情如 RPM, TPM。2. 檢查應(yīng)用部署架構(gòu)。1. 實(shí)現(xiàn)指數(shù)退避重試機(jī)制如使用 tenacity。2. 在應(yīng)用層增加請(qǐng)求隊(duì)列和速率限制。3. 考慮使用多個(gè)API密鑰進(jìn)行負(fù)載均衡。RAG 效果差檢索不到相關(guān)文檔1. 文檔切分chunk策略不合理。2. 向量化模型與查詢不匹配。3. 檢索 top_k 參數(shù)設(shè)置過小。1. 檢查 chunk 的大小和重疊度。2. 測(cè)試不同嵌入embedding模型。3. 人工評(píng)估檢索結(jié)果的相關(guān)性。1. 根據(jù)文檔類型調(diào)整 chunk 策略如按段落、按標(biāo)題。2. 嘗試在檢索后增加一個(gè)“重排序”步驟。3. 適當(dāng)增加 top_k并在后續(xù)步驟中進(jìn)行過濾。Agent 陷入循環(huán)或執(zhí)行錯(cuò)誤動(dòng)作1. Agent 的規(guī)劃Planning能力不足。2. 工具Tools的定義或返回結(jié)果不清晰。3. 缺少最大迭代次數(shù)的限制。1. 打印出 Agent 每一步的思考過程。2. 檢查工具調(diào)用的輸入輸出格式。1. 為 Agent 提供更詳細(xì)的指令和示例。2. 優(yōu)化工具的描述和輸出解析。3. 強(qiáng)制設(shè)置max_iterations或max_execution_time。9. 最佳實(shí)踐與工程建議要將 LLM 應(yīng)用從“玩具”升級(jí)為“工程”需要遵循一系列最佳實(shí)踐設(shè)計(jì)模式化思維鏈Chain-of-Thought對(duì)于復(fù)雜問題在提示詞中要求模型“逐步思考”這能顯著提升推理任務(wù)的準(zhǔn)確性。ReAct 模式讓 Agent 以Thought - Action - Observation的循環(huán)運(yùn)作將推理與工具調(diào)用結(jié)合。檢查-執(zhí)行模式先讓一個(gè)模型或同一模型生成計(jì)劃或代碼再讓另一個(gè)模型或驗(yàn)證器檢查其正確性最后執(zhí)行。測(cè)試驅(qū)動(dòng)開發(fā)為你的提示詞鏈和 Agent 創(chuàng)建單元測(cè)試和集成測(cè)試。使用包含各種邊界案例的測(cè)試集。評(píng)估指標(biāo)不應(yīng)只是“看起來不錯(cuò)”而應(yīng)量化如意圖分類準(zhǔn)確率、檢索相關(guān)性分?jǐn)?shù)、輸出與標(biāo)準(zhǔn)答案的相似度如使用 ROUGE, BLEU或通過另一個(gè) LLM 進(jìn)行評(píng)分LLM-as-a-Judge。配置與版本管理將提示詞模板、模型參數(shù)、溫度等配置外置如 YAML、JSON 文件不要硬編碼在代碼中。對(duì)提示詞和鏈的定義進(jìn)行版本控制如 Git。當(dāng)修改提示詞時(shí)能清晰地對(duì)比和回滾。安全與合規(guī)輸入過濾對(duì)用戶輸入進(jìn)行必要的清洗和過濾防止提示詞注入攻擊。輸出審查對(duì)模型輸出進(jìn)行內(nèi)容安全過濾避免生成有害、偏見或不合規(guī)的內(nèi)容。數(shù)據(jù)隱私了解模型供應(yīng)商的數(shù)據(jù)使用政策對(duì)于敏感數(shù)據(jù)考慮使用本地化模型或具有數(shù)據(jù)保密協(xié)議的供應(yīng)商。可觀測(cè)性建設(shè)除了基礎(chǔ)日志建立監(jiān)控儀表盤跟蹤關(guān)鍵指標(biāo)請(qǐng)求量、響應(yīng)延遲、Token 消耗、錯(cuò)誤率、模型調(diào)用分布。記錄每次用戶會(huì)話的完整追蹤Trace便于復(fù)現(xiàn)和調(diào)試復(fù)雜問題。成本優(yōu)化建立預(yù)算和告警機(jī)制。定期審查日志識(shí)別并優(yōu)化高消耗、低價(jià)值的查詢模式。考慮對(duì)非實(shí)時(shí)任務(wù)使用異步處理和批處理 API如果供應(yīng)商支持。構(gòu)建健康的 LLM 應(yīng)用是一個(gè)從“盲目調(diào)用”到“精細(xì)設(shè)計(jì)”從“關(guān)注輸出”到“關(guān)注全過程”的思維轉(zhuǎn)變。它要求開發(fā)者不僅是一個(gè) API 調(diào)用者更是一個(gè)系統(tǒng)架構(gòu)師。通過采用結(jié)構(gòu)化的提示詞、增加輸出護(hù)欄、實(shí)施成本感知策略、建立全面的可觀測(cè)性你可以顯著提升應(yīng)用的可靠性、效率與可控性。