Integrieren Sie einfach große Sprachmodelle in Ihren Python -Code. Verwenden Sie einfach die Dekorateure @prompt und @chatprompt , um Funktionen zu erstellen, die die strukturierte Ausgabe aus dem LLM zurückgeben. Mischen Sie LLM -Abfragen und Funktionen mit regulärem Python -Code, um komplexe Logik zu erstellen.
FunctionCall und ParallelFunctionCall Rückgabe aufruft.async def wenn Sie eine magentische Funktion definieren.pip install magenticoder mit UV
uv add magentic Konfigurieren Sie Ihre OpenAI -API -Taste, indem Sie die Umgebungsvariable OPENAI_API_KEY einstellen. Um einen anderen LLM -Anbieter zu konfigurieren, finden Sie eine Konfiguration für mehr.
Mit dem @prompt -Dekorator können Sie eine Vorlage für ein großes Sprachmodell (LLM) als Python -Funktion definieren. Wenn diese Funktion aufgerufen wird, werden die Argumente in die Vorlage eingefügt, dann wird diese Eingabeaufforderung an einen LLM gesendet, der die Funktionsausgabe erzeugt.
from magentic import prompt
@ prompt ( 'Add more "dude"ness to: {phrase}' )
def dudeify ( phrase : str ) -> str : ... # No function body as this is never executed
dudeify ( "Hello, how are you?" )
# "Hey, dude! What's up? How's it going, my man?" Der @prompt -Dekorateur respektiert die Annotation der dekorierten Funktion zurück. Dies kann jeder Typ sein, der von Pydantic unterstützt wird, einschließlich eines pydantic Modells.
from magentic import prompt
from pydantic import BaseModel
class Superhero ( BaseModel ):
name : str
age : int
power : str
enemies : list [ str ]
@ prompt ( "Create a Superhero named {name}." )
def create_superhero ( name : str ) -> Superhero : ...
create_superhero ( "Garden Man" )
# Superhero(name='Garden Man', age=30, power='Control over plants', enemies=['Pollution Man', 'Concrete Woman'])Weitere Informationen finden Sie in strukturierten Ausgängen.
Der Dekorateur @chatprompt funktioniert genau wie @prompt ermöglicht es Ihnen jedoch, Chat -Nachrichten als Vorlage und nicht als einzelne Textaufforderung zu übergeben. Dies kann verwendet werden, um eine Systemnachricht bereitzustellen oder um nur wenige Schüsse aufzufordern, bei denen Sie Beispielantworten angeben, um die Ausgabe des Modells zu leiten. Formatfelder, die von Curly -Braces {example} gekennzeichnet sind, werden in allen Nachrichten ausgefüllt (mit Ausnahme von FunctionResultMessage ).
from magentic import chatprompt , AssistantMessage , SystemMessage , UserMessage
from pydantic import BaseModel
class Quote ( BaseModel ):
quote : str
character : str
@ chatprompt (
SystemMessage ( "You are a movie buff." ),
UserMessage ( "What is your favorite quote from Harry Potter?" ),
AssistantMessage (
Quote (
quote = "It does not do to dwell on dreams and forget to live." ,
character = "Albus Dumbledore" ,
)
),
UserMessage ( "What is your favorite quote from {movie}?" ),
)
def get_movie_quote ( movie : str ) -> Quote : ...
get_movie_quote ( "Iron Man" )
# Quote(quote='I am Iron Man.', character='Tony Stark')Siehe Chat, um mehr zu fordern.
Ein LLM kann sich auch entscheiden, Funktionen anzurufen. In diesem Fall gibt die @prompt -dekorierte Funktion ein FunctionCall zurück, das aufgerufen werden kann, um die Funktion unter Verwendung der vom LLM bereitgestellten Argumente auszuführen.
from typing import Literal
from magentic import prompt , FunctionCall
def search_twitter ( query : str , category : Literal [ "latest" , "people" ]) -> str :
"""Searches Twitter for a query."""
print ( f"Searching Twitter for { query !r } in category { category !r } " )
return "<twitter results>"
def search_youtube ( query : str , channel : str = "all" ) -> str :
"""Searches YouTube for a query."""
print ( f"Searching YouTube for { query !r } in channel { channel !r } " )
return "<youtube results>"
@ prompt (
"Use the appropriate search function to answer: {question}" ,
functions = [ search_twitter , search_youtube ],
)
def perform_search ( question : str ) -> FunctionCall [ str ]: ...
output = perform_search ( "What is the latest news on LLMs?" )
print ( output )
# > FunctionCall(<function search_twitter at 0x10c367d00>, 'LLMs', 'latest')
output ()
# > Searching Twitter for 'Large Language Models news' in category 'latest'
# '<twitter results>'Sehen Sie die Funktion an, um mehr zu fordern.
Manchmal erfordert das LLM einen oder mehrere Funktionsaufrufe, um eine endgültige Antwort zu generieren. Der Dekorator @prompt_chain löst FunctionCall automatisch auf und übergibt die Ausgabe an die LLM, um fortzufahren, bis die endgültige Antwort erreicht ist.
Im folgenden Beispiel ruft bei describe_weather als LLM zuerst die Funktion get_current_weather auf, das Ergebnis davon, um seine endgültige Antwort zu formulieren, die zurückgegeben wird.
from magentic import prompt_chain
def get_current_weather ( location , unit = "fahrenheit" ):
"""Get the current weather in a given location"""
# Pretend to query an API
return {
"location" : location ,
"temperature" : "72" ,
"unit" : unit ,
"forecast" : [ "sunny" , "windy" ],
}
@ prompt_chain (
"What's the weather like in {city}?" ,
functions = [ get_current_weather ],
)
def describe_weather ( city : str ) -> str : ...
describe_weather ( "Boston" )
# 'The current weather in Boston is 72°F and it is sunny and windy.' LLM-betriebene Funktionen, die mit @prompt , @chatprompt und @prompt_chain erstellt wurden, können als functions an andere @prompt / @prompt_chain Dekoratoren geliefert werden, genau wie normale Python-Funktionen. Dies ermöglicht zunehmend komplexer LLM-betriebene Funktionen, während einzelne Komponenten isoliert getestet und verbessert werden können.
Die StreamedStr (und AsyncStreamedStr ) -Klasse kann verwendet werden, um die Ausgabe des LLM zu streamen. Auf diese Weise können Sie den Text verarbeiten, während er generiert wird, anstatt die gesamte Ausgabe gleichzeitig zu empfangen.
from magentic import prompt , StreamedStr
@ prompt ( "Tell me about {country}" )
def describe_country ( country : str ) -> StreamedStr : ...
# Print the chunks while they are being received
for chunk in describe_country ( "Brazil" ):
print ( chunk , end = "" )
# 'Brazil, officially known as the Federative Republic of Brazil, is ...' Mehrere StreamedStr kann gleichzeitig erstellt werden, um LLM -Ausgänge gleichzeitig zu streamen. Im folgenden Beispiel dauert das Erstellen der Beschreibung für mehrere Länder ungefähr die gleiche Zeit wie für ein einzelnes Land.
from time import time
countries = [ "Australia" , "Brazil" , "Chile" ]
# Generate the descriptions one at a time
start_time = time ()
for country in countries :
# Converting `StreamedStr` to `str` blocks until the LLM output is fully generated
description = str ( describe_country ( country ))
print ( f" { time () - start_time :.2f } s : { country } - { len ( description ) } chars" )
# 22.72s : Australia - 2130 chars
# 41.63s : Brazil - 1884 chars
# 74.31s : Chile - 2968 chars
# Generate the descriptions concurrently by creating the StreamedStrs at the same time
start_time = time ()
streamed_strs = [ describe_country ( country ) for country in countries ]
for country , streamed_str in zip ( countries , streamed_strs ):
description = str ( streamed_str )
print ( f" { time () - start_time :.2f } s : { country } - { len ( description ) } chars" )
# 22.79s : Australia - 2147 chars
# 23.64s : Brazil - 2202 chars
# 24.67s : Chile - 2186 chars Strukturierte Ausgänge können auch aus dem LLM gestreamt werden, indem die Annotation des Rückgabetyps Iterable (oder AsyncIterable ) verwendet werden. Auf diese Weise kann jedes Element verarbeitet werden, während der nächste generiert wird.
from collections . abc import Iterable
from time import time
from magentic import prompt
from pydantic import BaseModel
class Superhero ( BaseModel ):
name : str
age : int
power : str
enemies : list [ str ]
@ prompt ( "Create a Superhero team named {name}." )
def create_superhero_team ( name : str ) -> Iterable [ Superhero ]: ...
start_time = time ()
for hero in create_superhero_team ( "The Food Dudes" ):
print ( f" { time () - start_time :.2f } s : { hero } " )
# 2.23s : name='Pizza Man' age=30 power='Can shoot pizza slices from his hands' enemies=['The Hungry Horde', 'The Junk Food Gang']
# 4.03s : name='Captain Carrot' age=35 power='Super strength and agility from eating carrots' enemies=['The Sugar Squad', 'The Greasy Gang']
# 6.05s : name='Ice Cream Girl' age=25 power='Can create ice cream out of thin air' enemies=['The Hot Sauce Squad', 'The Healthy Eaters']Siehe Streaming für mehr.
Asynchrone Funktionen / Coroutinen können verwendet werden, um die LLM gleichzeitig abzufragen. Dies kann die Gesamtgeschwindigkeit der Erzeugung erheblich erhöhen und anderen asynchronen Code ausführen, während Sie auf die LLM -Ausgabe warten. Im folgenden Beispiel erzeugt das LLM eine Beschreibung für jeden US -Präsidenten, während er auf die nächste in der Liste wartet. Das Messen der pro Sekunde generierten Zeichen zeigt, dass dieses Beispiel eine 7x -Beschleunigung gegenüber der seriellen Verarbeitung erreicht.
import asyncio
from time import time
from typing import AsyncIterable
from magentic import prompt
@ prompt ( "List ten presidents of the United States" )
async def iter_presidents () -> AsyncIterable [ str ]: ...
@ prompt ( "Tell me more about {topic}" )
async def tell_me_more_about ( topic : str ) -> str : ...
# For each president listed, generate a description concurrently
start_time = time ()
tasks = []
async for president in await iter_presidents ():
# Use asyncio.create_task to schedule the coroutine for execution before awaiting it
# This way descriptions will start being generated while the list of presidents is still being generated
task = asyncio . create_task ( tell_me_more_about ( president ))
tasks . append ( task )
descriptions = await asyncio . gather ( * tasks )
# Measure the characters per second
total_chars = sum ( len ( desc ) for desc in descriptions )
time_elapsed = time () - start_time
print ( total_chars , time_elapsed , total_chars / time_elapsed )
# 24575 28.70 856.07
# Measure the characters per second to describe a single president
start_time = time ()
out = await tell_me_more_about ( "George Washington" )
time_elapsed = time () - start_time
print ( len ( out ), time_elapsed , len ( out ) / time_elapsed )
# 2206 18.72 117.78Weitere Informationen finden Sie in Asyncio.
functions für @prompt kann asynchrische/coroutine -Funktionen enthalten. Wenn die entsprechenden FunctionCall bezeichnet werden, müssen das Ergebnis erwartet werden.Annotated Typs können Beschreibungen und andere Metadaten für Funktionsparameter bereitgestellt werden. Siehe die pydantische Dokumentation zur Verwendung von Field , um Funktionsargumente zu beschreiben.@prompt und @prompt_chain akzeptieren auch ein model . Sie können eine Instanz von OpenaiChatModel übergeben, um GPT4 zu verwenden oder eine andere Temperatur zu konfigurieren. Siehe unten.@prompt -Funktionen verwendet werden, indem Sie dem Beispiel -Notizbuch für einen Pandas -Datenframe folgen. Magentic unterstützt mehrere "Backends" (LLM -Anbieter). Diese sind
openai : Das Standard -Backend, das das openai -Python -Paket verwendet. Unterstützt alle Merkmale von magentisch. from magentic import OpenaiChatModelanthropic : Verwendet das anthropic Python -Paket. Unterstützt alle Merkmale von Magentic, aber derzeit werden Streaming -Antworten auf einmal empfangen. pip install " magentic[anthropic] " from magentic . chat_model . anthropic_chat_model import AnthropicChatModellitellm : Verwendet das litellm Python -Paket, um LLMs von vielen verschiedenen Anbietern abzufragen. Hinweis: Einige Modelle unterstützen möglicherweise nicht alle Merkmale der magentic EG -Funktionsaufruf/strukturierten Ausgabe und Streaming. pip install " magentic[litellm] " from magentic . chat_model . litellm_chat_model import LitellmChatModelmistral : Verwendet das openai Python -Paket mit einigen kleinen Änderungen, um die API -Abfragen mit der Mistral -API kompatibel zu machen. Unterstützt alle Merkmale von Magentic, jedoch werden Werkzeugaufrufe (einschließlich strukturierter Ausgaben) nicht gestreamt, sodass alle gleichzeitig empfangen werden. HINWEIS: Eine zukünftige Version von Magentic könnte auf das mistral Python -Paket wechseln. from magentic . chat_model . mistral_chat_model import MistralChatModel Das von magentic verwendete Backend und LLM ( ChatModel ) kann auf verschiedene Weise konfiguriert werden. Wenn eine magentische Funktion aufgerufen wird, folgt das zu verwendende ChatModel dieser Reihenfolge der Präferenz
ChatModel -Instanz als model für den magentischen Dekorateur bereitgestelltwith MyChatModel:ChatModel , das aus Umgebungsvariablen erstellt wurde, und die Standardeinstellungen in SRC/Magentic/Settings.py from magentic import OpenaiChatModel , prompt
from magentic . chat_model . litellm_chat_model import LitellmChatModel
@ prompt ( "Say hello" )
def say_hello () -> str : ...
@ prompt (
"Say hello" ,
model = LitellmChatModel ( "ollama_chat/llama3" ),
)
def say_hello_litellm () -> str : ...
say_hello () # Uses env vars or default settings
with OpenaiChatModel ( "gpt-3.5-turbo" , temperature = 1 ):
say_hello () # Uses openai with gpt-3.5-turbo and temperature=1 due to context manager
say_hello_litellm () # Uses litellm with ollama_chat/llama3 because explicitly configuredDie folgenden Umgebungsvariablen können festgelegt werden.
| Umgebungsvariable | Beschreibung | Beispiel |
|---|---|---|
| Magentic_backend | Das Paket, das als LLM -Backend verwendet werden soll | anthropisch / openai / litellm |
| Magentic_anthropic_model | Anthropisches Modell | Claude-3-Haiku-20240307 |
| Magentic_anthropic_api_key | Anthropischer API -Schlüssel, der von magentisch verwendet werden soll | SK -... |
| Magentic_anthropic_base_url | Basis-URL für eine anthropisch kompatible API | http: // localhost: 8080 |
| Magentic_anthropic_max_tokens | Maximale Anzahl erzeugter Token | 1024 |
| Magentic_anthropic_temperature | Temperatur | 0,5 |
| Magentic_litellm_model | Litellm -Modell | Claude-2 |
| Magentic_litellm_api_base | Die Basis -URL zur Frage | http: // localhost: 11434 |
| Magentic_litellm_max_tokens | Litellm maximal Anzahl erzeugter Token | 1024 |
| Magentic_litellm_temperature | Litellm -Temperatur | 0,5 |
| Magentic_mistal_model | Mistral -Modell | Mistral-Large-Latest |
| Magentic_mistal_api_key | Mistral -API -Schlüssel, die von magentisch verwendet werden soll | Xeg ... |
| Magentic_mistal_base_url | Basis-URL für eine mistral-kompatible API | http: // localhost: 8080 |
| MAGENTIC_MISTRAL_MAX_TOKENS | Maximale Anzahl erzeugter Token | 1024 |
| Magentic_mistal_seed | Saatgut für deterministische Probenahme | 42 |
| Magentic_mistal_temperature | Temperatur | 0,5 |
| Magentic_openai_Model | Openai -Modell | GPT-4 |
| Magentic_openai_api_key | OpenAI -API -Schlüssel, der von magentisch verwendet werden soll | SK -... |
| Magentic_openai_api_type | Erlaubte Optionen: "Openai", "Azure" | azurblau |
| Magentic_openai_Base_url | Basis-URL für eine OpenAI-kompatible API | http: // localhost: 8080 |
| Magentic_openai_max_tokens | Openai maximale Anzahl erzeugter Token | 1024 |
| Magentic_openai_seed | Saatgut für deterministische Probenahme | 42 |
| Magentic_openai_Temperature | Offene Temperatur | 0,5 |
Wenn Sie das openai Backend verwenden, können Sie die Variable der MAGENTIC_OPENAI_BASE_URL oder verwenden Sie OpenaiChatModel(..., base_url="http://localhost:8080") in Code, magentic mit OpenAI-kompatiblen API-Azure Openai-Dienst zu verwenden, Litellm, Litellm, Litellm, Litellm, Litellm, Litellm, Litellm, Litellm, Litellm, Litellm, Litellm, Litellm, litellm, litellm, litellm, litellm, litellm, litellm, litellm, litellm, litellm, litellm, litellm, litellm, litellm, litellm, litellm, litellm, litellm, litellm, litellm, Litellm OpenAI Proxy Server, Localai. Beachten Sie, dass Sie, wenn die API keine Toolaufrufe unterstützt, nicht in der Lage sind, Eingabeaufführungen zu erstellen, die Python-Objekte zurückgeben, aber andere Merkmale von magentic funktionieren weiterhin.
Um Azure mit dem OpenAI -Backend zu verwenden, müssen Sie die Umgebungsvariable MAGENTIC_OPENAI_API_TYPE auf "Azure" einstellen oder OpenaiChatModel(..., api_type="azure") verwenden und auch die vom OpenAI -Paket benötigten Umgebungsvariablen festlegen. Siehe https://github.com/openai/openai-python#microsoft-azure-openai
Viele Typ -Checkers erheben Warnungen oder Fehler für Funktionen mit dem @prompt -Dekorator, da die Funktion keinen Körper oder keinen Rückgabewert hat. Es gibt verschiedene Möglichkeiten, mit diesen umzugehen.
empty-body . # pyproject.toml
[ tool . mypy ]
disable_error_code = [ " empty-body " ]... (das befriedigt MyPy nicht) oder raise . @ prompt ( "Choose a color" )
def random_color () -> str : ...# type: ignore[empty-body] für jede Funktion. In diesem Fall können Sie eine Docstring anstelle von ... hinzufügen. @ prompt ( "Choose a color" )
def random_color () -> str : # type: ignore[empty-body]
"""Returns a random color."""