Heim >Backend-Entwicklung >Python-Tutorial >Grundlegende Praktiken zum Erstellen robuster LLM-Anwendungen
Ich habe LLM-Anwendungen in der Cloud erstellt. Ich habe auch viele Entwickler gesehen, die LLM-Apps erstellen, die sich hervorragend für ein MVP oder einen Prototyp eignen und einige Arbeit erfordern, um sie produktionsreif zu machen. Eine oder mehrere der aufgeführten Vorgehensweisen können bei Anwendung dazu beitragen, dass Ihre Anwendung effektiv skaliert wird. Dieser Artikel behandelt nicht den gesamten Software-Engineering-Aspekt der Anwendungsentwicklung, sondern nur die LLM-Wrapper-Anwendungen. Außerdem sind die Codeausschnitte in Python und die gleiche Logik kann auch auf andere Sprachen angewendet werden.
Verwenden Sie Middleware wie LiteLLM oder LangChain, um Vendor-Lock-in zu vermeiden und einfach zwischen Modellen zu wechseln, während sie sich weiterentwickeln.
Python:
from litellm import completion response = completion( model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Hello, how are you?"}] )
Middleware-Lösungen wie LiteLLM und LangChain bieten eine Abstraktionsebene zwischen Ihrer Anwendung und verschiedenen LLM-Anbietern. Diese Abstraktion ermöglicht Ihnen den einfachen Wechsel zwischen verschiedenen Modellen oder Anbietern, ohne Ihren Kernanwendungscode zu ändern. Da sich die KI-Landschaft schnell weiterentwickelt, werden häufig neue Modelle mit verbesserten Funktionen veröffentlicht. Durch den Einsatz von Middleware können Sie diese neuen Modelle schnell übernehmen oder den Anbieter je nach Leistung, Kosten oder Funktionsanforderungen wechseln und so sicherstellen, dass Ihre Anwendung aktuell und wettbewerbsfähig bleibt.
Vermeiden Sie Probleme mit der Ratenbegrenzung, indem Sie Wiederholungslogik in Ihren API-Aufrufen implementieren.
Python:
import time from openai import OpenAI client = OpenAI() def retry_api_call(max_retries=3, delay=1): for attempt in range(max_retries): try: response = client.chat.completions.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Hello!"}] ) return response except Exception as e: if attempt == max_retries - 1: raise e time.sleep(delay * (2 ** attempt)) # Exponential backoff
LLM-Anbieter legen häufig Tarifbegrenzungen fest, um Missbrauch zu verhindern und eine faire Nutzung sicherzustellen. Durch die Implementierung eines Wiederholungsmechanismus mit exponentiellem Backoff kann Ihre Anwendung vorübergehende Ausfälle oder Ratenbegrenzungsfehler ordnungsgemäß verarbeiten. Dieser Ansatz erhöht die Zuverlässigkeit Ihrer Anwendung, indem fehlgeschlagene Anfragen automatisch wiederholt werden, wodurch die Wahrscheinlichkeit von Dienstunterbrechungen aufgrund vorübergehender Probleme verringert wird. Die exponentielle Backoff-Strategie (Erhöhung der Verzögerung zwischen Wiederholungsversuchen) trägt dazu bei, zu verhindern, dass die API mit sofortigen Neuanforderungen überlastet wird, was Probleme mit der Ratenbegrenzung verschlimmern könnte.
Verlassen Sie sich nicht auf einen einzelnen LLM-Anbieter. Implementieren Sie Fallbacks, um Kontingentprobleme oder Serviceunterbrechungen zu bewältigen.
from litellm import completion def get_llm_response(prompt): providers = ['openai/gpt-3.5-turbo', 'anthropic/claude-2', 'cohere/command-nightly'] for provider in providers: try: response = completion(model=provider, messages=[{"role": "user", "content": prompt}]) return response except Exception as e: print(f"Error with {provider}: {str(e)}") continue raise Exception("All LLM providers failed")
Wenn Sie sich auf einen einzelnen LLM-Anbieter verlassen, kann es zu Dienstunterbrechungen kommen, wenn bei diesem Anbieter Ausfallzeiten auftreten oder Sie Kontingentgrenzen erreichen. Durch die Implementierung von Fallback-Optionen stellen Sie den kontinuierlichen Betrieb Ihrer Anwendung sicher. Dieser Ansatz ermöglicht es Ihnen auch, die Stärken verschiedener Anbieter oder Modelle für verschiedene Aufgaben zu nutzen. LiteLLM vereinfacht diesen Prozess, indem es eine einheitliche Schnittstelle für mehrere Anbieter bereitstellt und so den Wechsel zwischen ihnen oder die Implementierung von Fallback-Logik erleichtert.
Verwenden Sie Tools wie Langfuse oder Helicone für die LLM-Ablaufverfolgung und das Debugging.
from langfuse.openai import OpenAI client = OpenAI( api_key="your-openai-api-key", langfuse_public_key="your-langfuse-public-key", langfuse_secret_key="your-langfuse-secret-key" ) response = client.chat.completions.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Hello, AI!"}] )
Vorteile der Implementierung von Observability:
Observability-Tools liefern wichtige Einblicke in die Leistung, Nutzungsmuster und potenzielle Probleme Ihrer LLM-Anwendung. Sie ermöglichen Ihnen die Überwachung und Analyse von Interaktionen mit LLMs in Echtzeit und helfen Ihnen, Eingabeaufforderungen zu optimieren, Engpässe zu identifizieren und die Qualität der KI-generierten Antworten sicherzustellen. Dieses Maß an Sichtbarkeit ist für die Wartung, Fehlerbehebung und Verbesserung Ihrer Anwendung im Laufe der Zeit von entscheidender Bedeutung.
Verwenden Sie Eingabeaufforderungsverwaltungstools mit Versionierung, anstatt Eingabeaufforderungen in Ihren Code- oder Textdateien fest zu codieren.
from promptflow import PromptFlow pf = PromptFlow() prompt_template = pf.get_prompt("greeting_prompt", version="1.2") response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": prompt_template.format(name="Alice")}] )
Effektives Prompt-Management ist entscheidend für die Pflege und Verbesserung Ihrer LLM-Anwendung. Mithilfe spezieller Tools zur Eingabeaufforderungsverwaltung können Sie die Versionskontrolle Ihrer Eingabeaufforderungen durchführen, verschiedene Varianten A/B-Tests durchführen und sie problemlos in Ihrer gesamten Anwendung aktualisieren. Dieser Ansatz trennt die Eingabeaufforderungslogik vom Anwendungscode und erleichtert so die Iteration von Eingabeaufforderungen, ohne die Kernanwendung zu ändern. Es ermöglicht auch nicht-technischen Teammitgliedern, zu schnellen Verbesserungen beizutragen und ermöglicht eine bessere Zusammenarbeit bei der Verfeinerung von KI-Interaktionen.
Use a persistent cache like Redis for storing conversation history instead of in-memory cache which is not adapted for distributed systems.
from langchain.memory import RedisChatMessageHistory from langchain.chains import ConversationChain from langchain.llms import OpenAI # Initialize Redis chat message history message_history = RedisChatMessageHistory(url="redis://localhost:6379/0", ttl=600, session_id="user-123") # Create a conversation chain with Redis memory conversation = ConversationChain( llm=OpenAI(), memory=message_history, verbose=True ) # Use the conversation response = conversation.predict(input="Hi there!") print(response) # The conversation history is automatically stored in Redis
Storing conversation history is essential for maintaining context in ongoing interactions and providing personalized experiences. Using a persistent cache like Redis, especially in distributed systems, ensures that conversation history is reliably stored and quickly accessible. This approach allows your application to scale horizontally while maintaining consistent user experiences across different instances or servers. The use of Redis with LangChain simplifies the integration of persistent memory into your conversational AI system, making it easier to build stateful, context-aware applications.
Whenever possible like extracting structured information, provide a JSON schema instead of relying on raw text output.
import openai response = openai.ChatCompletion.create( model="gpt-3.5-turbo-1106", response_format={"type": "json_object"}, messages=[ {"role": "system", "content": "Extract the name and age from the user's input."}, {"role": "user", "content": "My name is John and I'm 30 years old."} ] ) print(response.choices[0].message.content) # Output: {"name": "John", "age": 30}
Using JSON mode for information extraction provides a structured and consistent output format, making it easier to parse and process the LLM's responses in your application. This approach reduces the need for complex post-processing of free-form text and minimizes the risk of misinterpretation. It's particularly useful for tasks like form filling, data extraction from unstructured text, or any scenario where you need to integrate AI-generated content into existing data structures or databases.
Implement alerts for prepaid credits and per-user credit checks, even in MVP stages.
def check_user_credits(user_id, requested_tokens): user_credits = get_user_credits(user_id) if user_credits < requested_tokens: raise InsufficientCreditsError(f"User {user_id} has insufficient credits") remaining_credits = user_credits - requested_tokens if remaining_credits < CREDIT_ALERT_THRESHOLD: send_low_credit_alert(user_id, remaining_credits) return True
Implementing credit alerts and per-user credit checks is crucial for managing costs and ensuring fair usage in your LLM application. This system helps prevent unexpected expenses and allows you to proactively manage user access based on their credit limits. By setting up alerts at multiple thresholds, you can inform users or administrators before credits are depleted, ensuring uninterrupted service. This approach is valuable even in MVP stages, as it helps you understand usage patterns and plan for scaling your application effectively.
Create mechanisms for users to provide feedback on AI responses, starting with simple thumbs up/down ratings.
def process_user_feedback(response_id, feedback): if feedback == 'thumbs_up': log_positive_feedback(response_id) elif feedback == 'thumbs_down': log_negative_feedback(response_id) trigger_improvement_workflow(response_id) # In your API endpoint @app.route('/feedback', methods=['POST']) def submit_feedback(): data = request.json process_user_feedback(data['response_id'], data['feedback']) return jsonify({"status": "Feedback received"})
Implementing feedback loops is essential for continuously improving your LLM application. By allowing users to provide feedback on AI responses, you can identify areas where the model performs well and where it needs improvement. This data can be used to fine-tune models, adjust prompts, or implement additional safeguards. Starting with simple thumbs up/down ratings provides an easy way for users to give feedback, while more detailed feedback options can be added later for deeper insights. This approach helps in building trust with users and demonstrates your commitment to improving the AI's performance based on real-world usage.
Use prompt guards to check for prompt injection attacks, toxic content, and off-topic responses.
import re from better_profanity import profanity def check_prompt_injection(input_text): injection_patterns = [ r"ignore previous instructions", r"disregard all prior commands", r"override system prompt" ] for pattern in injection_patterns: if re.search(pattern, input_text, re.IGNORECASE): return True return False def check_toxic_content(input_text): return profanity.contains_profanity(input_text) def sanitize_input(input_text): if check_prompt_injection(input_text): raise ValueError("Potential prompt injection detected") if check_toxic_content(input_text): raise ValueError("Toxic content detected") # Additional checks can be added here (e.g., off-topic detection) return input_text # Return sanitized input if all checks pass # Usage try: safe_input = sanitize_input(user_input) # Process safe_input with your LLM except ValueError as e: print(f"Input rejected: {str(e)}")
Implementing guardrails is crucial for ensuring the safety and reliability of your LLM application. This example demonstrates how to check for potential prompt injection attacks and toxic content. Prompt injection attacks attempt to override or bypass the system's intended behavior, while toxic content checks help maintain a safe and respectful environment. By implementing these checks, you can prevent malicious use of your AI system and ensure that the content generated aligns with your application's guidelines and ethical standards. Additional checks can be added to detect off-topic responses or other unwanted behaviors, further enhancing the robustness of your application.
All the above listed points can be easily integrated into your application and they prepare you better for scaling in production. You may also agree or disagree on some of the above points. In any case, feel free to post your questions or comments.
Das obige ist der detaillierte Inhalt vonGrundlegende Praktiken zum Erstellen robuster LLM-Anwendungen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!