תהליכים

תהליכים הם פונקציות עטופות עם כמה מאפיינים נוספים בהשוואה לשיחות ישירות: הן בעלות סוג חזק, ניתנות להעברה בסטרימינג, אפשר להפעיל אותן באופן מקומי ומרוחק, והן ניתנות למעקב מלא. Genkit מספק כלים ל-CLI ולממשק המשתמש למפתחים להרצה ולניפוי באגים של תהליכים.

הגדרת תהליכים

בצורתו הפשוטה ביותר, תהליך הוא רק גרסה עטופה של פונקציה:

menuSuggestionFlow := genkit.DefineFlow(
	g,
	"menuSuggestionFlow",
	func(ctx context.Context, restaurantTheme string) (string, error) {
		suggestion := makeMenuItemSuggestion(restaurantTheme)
		return suggestion, nil
	})

כך תוכלו להריץ את הפונקציה מ-CLI של Genkit ומממשק המשתמש למפתחים. זו גם דרישה לשימוש בהרבה מהתכונות של Genkit, כולל פריסה וניטור.

יתרון חשוב של תהליכים ב-Genkit על פני קריאה ישירה ל-API של מודל הוא בטיחות הסוג של הקלט והפלט. סוגי הארגומנט והתוצאה של תהליך יכולים להיות ערכים פשוטים או מובְנים. Genkit ייצור סכימות JSON לערכים האלה באמצעות invopop/jsonschema.

התהליך הבא מקבל string כקלט ומפיק struct כפלט:

type MenuSuggestion struct {
	ItemName    string `json:"item_name"`
	Description string `json:"description"`
	Calories    int    `json:"calories"`
}

menuSuggestionFlow := genkit.DefineFlow(
	g,
	"menuSuggestionFlow",
	func(ctx context.Context, restaurantTheme string) (MenuSuggestion, error) {
		suggestion := makeStructuredMenuItemSuggestion(restaurantTheme)
		return suggestion, nil
	},
)

תהליכי עבודה שפועלים

כדי להריץ תהליך בקוד:

suggestion, err := menuSuggestionFlow.Run(context.Background(), "French")

אפשר להשתמש ב-CLI גם כדי להריץ תהליכים:

genkit flow:run menuSuggestionFlow '"French"'

שודר

דוגמה פשוטה לתהליך שיכול להעביר ערכים בסטרימינג:

// Types for illustrative purposes.
type InputType string
type OutputType string
type StreamType string

menuSuggestionFlow := genkit.DefineStreamingFlow(
	g,
	"menuSuggestionFlow",
	func(
		ctx context.Context,
		restaurantTheme InputType,
		callback func(context.Context, StreamType) error,
	) (OutputType, error) {
		var menu strings.Builder
		menuChunks := make(chan StreamType)
		go makeFullMenuSuggestion(restaurantTheme, menuChunks)
		for {
			chunk, ok := <-menuChunks
			if !ok {
				break
			}
			if callback != nil {
				callback(context.Background(), chunk)
			}
			menu.WriteString(string(chunk))
		}
		return OutputType(menu.String()), nil
	},
)

שימו לב שאפשר לא להגדיר את הפונקציה הזו. הוא מוגדר רק אם הלקוח שמפעיל את הפונקציה מבקש תשובה בסטרימינג.

כדי להפעיל תהליך במודל סטרימינג:

menuSuggestionFlow.Stream(
	context.Background(),
	"French",
)(func(sfv *core.StreamFlowValue[OutputType, StreamType], err error) bool {
	if err != nil {
		// handle err
		return false
	}
	if !sfv.Done {
		fmt.Print(sfv.Stream)
		return true
	} else {
		fmt.Print(sfv.Output)
		return false
	}
})

אם התהליך לא מטמיע סטרימינג, StreamFlow() מתנהג באופן זהה ל-RunFlow().

אפשר גם להשתמש ב-CLI כדי להעביר תהליכים בסטרימינג:

genkit flow:run menuSuggestionFlow '"French"' -s

פריסת תהליכים

כדי שתוכלו לגשת לתהליך דרך HTTP, תצטרכו לפרוס אותו קודם. כדי לפרוס תהליכים באמצעות Cloud Run ושירותים דומים, מגדירים את התהליכים ומפעילים את Init():

func main() {
	ctx := context.Background()
	g, err := genkit.Init(ctx)
	if err != nil {
		log.Fatal(err)
	}
	genkit.DefineFlow(
		g,
		"menuSuggestionFlow",
		func(ctx context.Context, restaurantTheme string) (string, error) {
			// ...
			return "", nil
		},
	)
	<-ctx.Done()
}

Init מפעיל שרת net/http שחושפ את הזרמים שלכם כנקודות קצה מסוג HTTP (לדוגמה, http://localhost:3400/menuSuggestionFlow).

הפרמטר השני הוא Options אופציונלי שמציין את הפרטים הבאים:

  • FlowAddr: הכתובת והיציאה שבהן מתבצעת ההאזנה. אם לא מציינים יציאה, השרת מקשיב ביציאה שצוינה במשתנה הסביבה PORT. אם המשתנה הזה ריק, המערכת משתמשת ביציאת ברירת המחדל 3400.
  • Flows: אילו תהליכים להציג. אם לא מציינים ערך, Init ישמש לכל התהליכים שהוגדרו.

אם רוצים להציג תהליכים באותו מארח ובאותה יציאה כמו נקודות קצה אחרות, אפשר להגדיר את FlowAddr כ-- ולקרוא במקום זאת ל-NewFlowServeMux() כדי לקבל טיפול לתהליכי Genkit, שאפשר לבצע בו מוליפסקס עם טיפולי הנתיבים האחרים:

mainMux := http.NewServeMux()
mainMux.Handle("POST /flow/myFlow", genkit.Handler(myFlow))

ניראות של Flow

לפעמים, כשמשתמשים ב-SDK של צד שלישי שלא עבר הטמעה למעקב, כדאי לראות אותו כשלב מעקב נפרד בממשק המשתמש למפתחים. כל מה שצריך לעשות הוא לעטוף את הקוד בפונקציה run.

genkit.DefineFlow(
	g,
	"menuSuggestionFlow",
	func(ctx context.Context, restaurantTheme string) (string, error) {
		themes, err := genkit.Run(ctx, "find-similar-themes", func() (string, error) {
			// ...
			return "", nil
		})

		// ...
		return themes, err
	})