KI -Agenten sind Staatsmaschinen, nicht DAGs
Mit Synth Machines können Benutzer AI Agent State Machines ( Synth ) erstellen und ausführen, indem sie eine SynthDefinition zur Definition eines strukturierten KI -Workflows bereitstellen.
Staatliche Maschinen sind ein leistungsstarkes Konstrukt, da sie es einem Domänenexperten ermöglichen, das Problem in Staaten und Übergänge zu dekonstruieren.
Übergänge zwischen Zuständen können dann einen LLM, ein Werkzeug, einen Datenprozess oder eine Mischung aus vielen Ausgängen aufrufen.
Installieren Sie das Paket. pip install synth_machine[openai,togetherai,anthropic] oder poetry add synth_machine[openai,togetherai,anthropic]
Fügen Sie entweder Ihre API -Anbieter -Umgebungsschlüssel ein, für die
# You only need to set the API providers you want to use.
export OPENAI_API_KUY=secret
export ANTHROPIC_API_KEY=secret
export TOGETHER_API_KEY=secret
pip install synth_machine[vllm,llamacpp] oder poetry add synth_machine[vllm,llamacpp]
Sie müssen wahrscheinlich CUDA, VLLM oder Lama.cpp für die lokale Verwendung einrichten.
Hilfreiche Links:
agent = Synth(
config: dict[SynthDefinition], # Synth state machine defining states, transitions and prompts.
tools=[], # List of tools the agent will use
memory={}, # Any existing memory to add on top of any model_config.initial_memory
rag_runner: Optional[RAG] = None # Define a RAG integration for your agent.
postprocess_functions = [] # Any glue code functions
store : ObjectStore = ObjectStore(":memory:") # Any files created by tools will automatically go to you object store
Die SynthDefinition finden Sie in synthdefinitionsdocs oder synth_machine/synth_definition.py. Die pydantischen Basemodellen, aus denen sich SynthDefinition zusammensetzt, werden die genaueste Darstellung eines Synth sein.
Wir erwarten, dass die Spezifikation Aktualisierungen zwischen den wichtigsten Versionen aufweist.
Zu jedem Zeitpunkt können Sie den aktuellen Zustand und die nächsten Auslöser überprüfen
# Check state
agent.current_state()
# Triggers
agent.interfaces_for_available_triggers()
await agent.trigger(
"[trigger_name]",
params={
"input_1": "hello"
}
)
Batch -Übergangsaufrufe geben jede in diesem Übergang generierte Ausgangsvariable aus.
await agent.streaming_trigger(
"[trigger_name]",
params={
"input_1": "hello"
}
)
Streaming -Antworten ergeben eines der folgenden Ereignisse:
class YieldTasks(StrEnum):
CHUNK = "CHUNK"
MODEL_CONFIG = "MODEL_CONFIG"
SET_MEMORY = "SET_MEMORY"
SET_ACTIVE_OUTPUT = "SET_ACTIVE_OUTPUT"
CHUNK : LLM -Generationen werden jeweils von Chunks ein Token gesendet.MODEL_CONFIG : ergibt, welcher ausführender ausführer derzeit für beliebiger spezifische frontend interfaces verwendet wird.SET_MEMORP : Sendet Ereignisse neue Speichervariablen einSET_ACTIVE_OUTPUT : Ergibt den aktuellen Trigger der Übergangsausgabe. Auf diese Weise können Benutzer mit trigger experimentieren und dann in Echtzeit -Stream -LLM -Generationen in Benutzer mithilfe von Server -Side -Ereignissen (SSE) und trigger_streaming integrieren.
Wir bieten mehreren Ausführern, lokale oder API -gesteuerte LLM -Chat -Abschlüsse zu generieren.
openai : https://openai.com/api/pricing/togetherai : https://docs.together.ai/docs/inference-modelsanthropic : https://docs.anthropic.com/en/docs/models-overviewgoogle : https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/overview VLLM : https://github.com/vllm-project/vllmLlama-CPP : https://github.com/ggerganov/llama.cpp Model Config Sie können den Anbieter und das Modell entweder in default-model-config und in der Synth Base oder model_config bei der Übergangsausgabe angeben.
ModelConfig:
...
executor: [openai|togetherai|anthropic|vllm|llamacpp]
llm_name: [model_name]
Agentengedächtnis ist ein Wörterbuch, das alle Zwischenvariablen enthält, die in früheren Zuständen und Menschen / Systemeingaben erstellt werden.
agent.memory
# -> {
# "[memory_key]": [memory_value]
# }
Postprozessfunktionen sollten nur für den grundlegenden Klebercode verwendet werden, alle wichtigen Funktionen sollten in Tools integriert werden.
Gehen Sie zu "./tools/tofuTool/api.py um die Funktionalität anzuzeigen.
API starten
cd tools/tofuTool
poetry install
poetry run uvicorn api:app --port=5001 --reload
API -Spezifikation abrufen
curl -X GET http://localhost:5001/openapi.json > openapi_schema.json
Werkzeug definieren
Sie können ein Tool als solches mit nur dem Namen, dem API -Endpunkt und dem Tool OpenAPI -Schema definieren.
tofu_tool = Tool(
name="tofu_tool",
api_endpoint="http://localhost:5001",
api_spec=tool_spec
)
Abrufener Augemented Generation ist ein leistungsstarkes Instrument zur Verbesserung der LLM -Antworten, indem semantisch ähnliche Beispiele oder Ausübung des Materials, das das LLM erzeugt, anbietet.
synth_machine ist flexibel, so lange Sie von synth_machine.RAG erben und erstellen:
embed(documents: List[str]) undquery(prompt: str, rag_config: Optional[synth_machine.RAGConfig])Es ist einfach, mehrere Anbieter und Vektor -Datenbanken zu integrieren. Im Laufe der Zeit wird es unterstützt und Community -Lag -Implementierungen in einer Vielzahl von Einbettungsanbietern und Vektordatenbanken.
Die folgende Lappenklasse ist ideal, um mit lokalen Lag -Setups auf der CPU zu experimentieren.
pip install qdrant-client, fastembed
Definieren Sie die Klassenklasse
from synth_machine.rag import RAG
from qdrant_client import AsyncQdrantClient
from fastembed import TextEmbedding
from typing import List, Optional
from qdrant_client.models import Distance, VectorParams, PointStruct
class Qdrant(RAG):
"""
VectorDB: Qdrant - https://github.com/qdrant/qdrant
Embeddings: FastEmbed - https://github.com/qdrant/fastembed
This provides fast and lightweight on-device CPU embeddings creation and
similarity search using Qdrant in memory.
"""
def __init__(
self,
collection_name: str,
embedding_model: str="BAAI/bge-small-en-v1.5",
embedding_dimensions: int=384,
embedding_threads: int=-1,
qdrant_location: str=":memory:",
):
self.embedding_model = TextEmbedding(
model_name=embedding_model,
threads=embedding_threads
)
self.embedding_dimensions = embedding_dimensions
self.qdrant = AsyncQdrantClient(qdrant_location)
self.collection_name = collection_name
async def create_collection(self) -> bool:
if await self.qdrant.collection_exists(self.collection_name):
return True
else:
return await self.qdrant.create_collection(
collection_name=self.collection_name,
vectors_config=VectorParams(
size=self.embedding_dimensions, # maps to 'BAAI/bge-small-en-v1.5' model dimensions
distance=Distance.COSINE
)
)
async def embed(self, documents: List[str], metadata: Optional[List[dict]]=None):
if metadata and len(documents) != len(metadata):
raise ValueError("documents and metadata must be the same length")
embedding_list = list(
self.embedding_model.embed(documents)
)
upsert_response = await self.qdrant.upsert(
collection_name=self.collection_name,
points=[
PointStruct(
id=i,
vector=list(vector),
payload=metadata[i]
)
for i, vector in enumerate(embedding_list)
]
)
return upsert_response.status
async def query(self, prompt: str, rag_config: RAGConfig) -> List[dict]:
embedding = next(self.embedding_model.embed([prompt]))
similar_responses = await self.qdrant.search(
collection_name=self.collection_name,
query_vector=embedding,
limit=rag_config.n
)
return [
point.payload for point in similar_responses
]
Initiieren Sie nun die QDrant -Klasse und geben Sie bei der Definition Synth an.
qdrant = Qdrant(collection_name="tofu_examples")
await qdrant.create_collection()
agent = Synth(
...
rag_runner=Qdrant
)
Tools können eine Vielzahl verschiedener Objekte zurückgeben. Jede von einem Tool erstellte Datei wird automatisch zu Ihrem agent.store gelten. Wir verwenden ObjectStore für Dateispeicher mit ObjectStore(":memory:") als Standard.
So abrufen eine Datei: agent.store.get(file_name)
ObjectStore ermöglicht eine einfache Integration zu:
from synth_machine.machine import ObjectStore
agent = Agent(
...
store=ObjectStore("gs://[bucket_name]/[prefix]))
)
Jede benutzerdefinierte Funktionalität kann als benutzerdefinierte Funktion (UDF) definiert werden.
Diese nehmen Synth.memory als Eingabe und ermöglicht es Ihnen, benutzerdefinierte Funktionen als Teil der synth-machine auszuführen.
# Define postprocess function
from synth_machine.user_defined_functions import udf
@udf
def abc_postprocesss(memory):
...
return memory["variable_key"]
agent = Synth(
...
user_defined_functions = {
"abc": abc_postprocess
}
)
...
- key: trigger_udf
inputs:
- key: variable_key
outputs:
- key: example_udf
udf: abc
HINWEIS: Jede nicht triviale Funktionalität sollte ein Werkzeug und nicht ein UDF sein.