ملاحظة: تم إهمال هذه المكتبة ، يتم تقسيمها الآن إلى Zod-GPT و LLM-API.

مجموعة أدوات هندسة TypeScript-First Form للعمل مع نماذج اللغة الكبيرة القائمة على الدردشة (LLMS).
Llamaflow هي طبقة البرامج الوسيطة التي تقع بين برنامجك ونموذج الذكاء الاصطناعي ، فهي تضيف القدرات التالية أعلى واجهة برمجة تطبيقات الانتهاء من الدردشة القياسية:
مع llamaflow ، يمكنك ببساطة الاستعلام عن طراز chatgpt من Openai مثل SO:
import { OpenAI } from 'llama-flow' ;
const model = new OpenAI ( { apiKey : 'YOUR_OPENAI_KEY' } ) ;
const chat = model . chat ( {
systemMessage :
"You are a smart and honest AI assistant. Follow the user's requirements carefully & to the letter, minimize any other prose." ,
} ) ;
const response = await chat . request (
prompt . json ( {
message :
'What are some good names for childrens book about the renaissance? Respond as a JSON array' ,
schema : z . array ( z . string ( ) . max ( 200 ) ) ,
} ) ,
) ;
console . log ( response . content ) ; // content will be typed as string[]; يتم استضافة هذه الحزمة على NPM:
npm i llama-flow
yarn add llama-flow
لإعداد في قاعدة كودك ، قم بتهيئة مثيل جديد مع النموذج الذي تريده (فقط OpenAI محمص في الوقت الحالي). لاحظ أنه يمكنك أيضًا إضافة النموذج الافتراضي وتكوين الدردشة (مثل درجة الحرارة ، والمهلات ، وإعادة المحاولة) عند التهيئة. هذه مجرد تقصير ، ويمكن دائمًا الكتابة في وقت لاحق على أساس لكل سلسلة أو لكل طلب.
import { OpenAI } from 'llama-flow' ;
const model = new OpenAI (
{ apiKey : 'YOUR_OPENAI_KEY' } ,
{ model : 'gpt-3.5-turbo' } ,
) ;الدردشة هي محادثة بين "المستخدم" (البرنامج الخاص بك) ، ووكيل الذكاء الاصطناعى. ستهتم LlamaFlow بإدارة ذاكرة الدردشة ، بحيث يمكنك ببساطة متابعة المحادثة عن طريق إرسال طلب آخر. لاحظ أنه سيتم إضافة استراتيجيات مختلفة لإدارة الذاكرة في المستقبل ، مثل تقليم الذاكرة حسب الحاجة لتناسب نافذة السياق.
const chat = model . chat ( {
systemMessage : 'You are an AI writer.' ,
retainMemory : true ,
} ) ;
// You can ask the AI model with a simple string, or a dedicated `Prompt` object.
const response = await chat . request (
prompt . text (
'Write a script for a tiktok video that talks about the artistic contribution of the renaissance.' ,
) ,
) ;
// The results, as well as any usage stats, will be returned.
console . log (
`The AI writer's response is: ${ response . content } . Token used: ${ response . usage . totalTokens } .` ,
) ;
// You can follow up on this chat by prompting further, using the `bulletPrompt` object that was created earlier.
const bulletPoints = await chat . request ( bulletPrompt ) ;
// `bulletPoints.content` will be automatically casted in the correct type as defined in the schema field of `bulletPrompt`
console . log (
`The structured version of this response is: ${ JSON . stringify (
bulletPoints . content ,
) } ` ,
) ;المطالبة هي رسالة إلى دردشة منظمة العفو الدولية مع توقع تنسيق استجابة معين. يتم التحقق من صحة رسائل نوع المطالبة للتأكد من إرجاع التنسيق المحدد بالضبط ، أو أنه سيتم خطأ. هناك أنواع مختلفة من المطالبات لتنسيقات مختلفة. فيما يلي مثال على موجه JSON.
import { prompt } from 'llama-flow' ;
import { z } from 'zod' ; // JSON prompt uses Zod for schema validation.
const bulletPrompt = prompt . json ( {
message :
'Please rewrite this in a list of bullet points. Respond as a JSON array, where each element in the array is one bullet point. Keep each bullet point to be 200 characters max. For example: ["bullet point 1", "bullet point 2"]' ,
schema : z . array ( z . string ( ) . max ( 200 ) ) ,
} ) ; لاحظ أن الكائن Prompt يفصل message الرئيسية ، و formatMessage . يستخدم هذا لإعادة المحاكاة. عندما يستخدم LlamaFlow هذه المطالبة ، سوف يطلب النموذج مع كل من الرسالة الرئيسية والتنسيق. إذا عاد النموذج باستخدام استجابة منسقة بشكل غير صحيح ، فسيطلب من النموذج تصحيح الإخراج السابق ، باستخدام formatMessage فقط.
يمكنك إنشاء كائنات موجهة خاصة بك مع صحة مخصصة أيضًا. يوفر LlamaFlow طريقة سهلة وقابلة للتمديد لبناء أي نوع من المدققين. فيما يلي بعض الأمثلة على المدققين المخصصين:
مع أخذ المثال السريع أعلاه ، ولكن هذه المرة ، سيطلب من النموذج الرد فقط في نقاط الرصاص الفعلية بدلاً من صفائف JSON. هذا مفيد لأن النموذج (ESP <GPT-4) في بعض الأحيان ليس هو الأفضل في اتباع تعليمات التنسيق المحددة ، خاصة عندما يتعلق الأمر بهياكل البيانات المعقدة.
import { prompt } from 'llama-flow' ;
const bulletPrompt = prompt . json ( {
message :
'Please rewrite this in a list of bullet points. Respond as a list of bullet points, where each bullet point begins with the "-" character. Each bullet point should be less than 200 characters. Put each bullet point on a new line.' ,
// parse the response from the model so it can be fed into the schema validator
parseResponse : ( res ) => res . split ( 'n' ) . map ( ( s ) => s . replace ( '-' , '' ) . trim ( ) ) ,
// it's useful to define custom error messages, any schema parse errors will be automatically fed back into the model on retry, so the model knows exactly what to correct.
schema : z . array (
z . string ( ) . max ( 200 , {
message : 'This bullet point should be less than 200 characters.' ,
} ) ,
) ,
} ) ; الآن ، دعونا نأخذ هذا أبعد من ذلك. يمكنك إنشاء موجه يستخدم النموذج (أو بعض المصدر الخارجي الآخر) للتحقق من صحة إخراجه. يمكنك القيام بذلك عن طريق تمرير طريقة validate Async مخصصة. لاحظ أن هذه الطريقة ستجاوز الخصائص الأخرى ذات الصلة بالتحقق ، مثل formatMessage ، parseResponse ، schema .. إلخ.
import { prompt , Chat } from 'llama-flow' ;
const factCheckerChat = model . chat ( {
systemMessage :
'You are a fact checker that responds to if the user's messages are true or not, with just the word "true" or "false". Do not add punctuations or any other text. If the user asks a question, request, or anything that cannot be fact checked, ignore the user's request and just say "null".' ,
// The fact checker is designed to fulfill each request independently (e.g. the current request does not depend on the content of the previous request). So no need to keep message memory to save on tokens.
retainMemory : false ,
} ) ;
const buildFactCheckedPrompt = ( article : string ) =>
prompt . text ( {
message : `Please write a summary about the following article: ${ article } ` ,
// Because LLM driven validation can get expensive, set a lower retry count.
promptRetries : 2 ,
parse : async ( response ) => {
// Check if this summary is true or not
const { response } = await factCheckerChat . request (
prompt . boolean ( {
message : response . content ,
} ) ,
) ;
if ( response . content === true ) {
return { success : true , data : response . content } ;
} else {
// if `retryPrompt` is set, LLamaFlow will automatically retry with the text in this property.
return {
success : false ,
retryPrompt :
'This summary is not true, please rewrite with only true facts.' ,
} ;
}
} ,
} ) ;
// now, every content generated by this chat will be fact checked by the LLM itself, and this request will throw an error if the content can't be fixed (once the maximum number of retries has been reached).
const factCheckedContent = await chat . request (
buildFactCheckedPrompt (
'Write a script for a tiktok video that talks about the artistic contribution of the renaissance.' ,
) ,
) ;نظرًا لأن هذه واجهة برمجة تطبيقات ، فغالبًا ما يكون من المفيد الاستمرار في طلبها من نفس الدردشة. غالبًا ما يكون سجل الرسالة بمثابة سياق للطلب التالي. مثال جيد على استخدام حالة استخدام مثال على كتابة بعض المحتوى أولاً ، ثم استخراج الكيانات ، وأخيراً ، قدم بعض الخيارات للعنوان.
// You can reset chat history anytime with `reset()`, however, this is an anti-pattern, as it is prone to mistakes. It's much safer to just initialize a new chat.
chat . reset ( ) ;
const article = await chat . request (
prompt . text ( 'Write a blog post about the financial crisis of 2008' ) ,
) ;
const entities = await chat . request (
prompt . json ( {
message :
'What are the different entities in the above blog post? Respond in a JSON array, where the items in the array are just the names of the entities.' ,
schema : z . array ( z . string ( ) ) ,
} ) ,
) ;
const titles = await chat . request (
prompt . bulletPoints ( {
message : 'Write a good title for this post' ,
amount : 10 ,
} ) ,
) ; هناك خطأ شائع في واجهات برمجة تطبيقات LLM هو استخدام الرمز المميز - لا يُسمح لك إلا بتناسب كمية معينة من البيانات في نافذة السياق. في حالة LlamaFlow ، هذا يعني أنك محدودة في إجمالي عدد الرسائل التي يمكنك إرسالها (إذا تم ضبط retainMemory على true ) وطول محتوى الرسائل.
سيحدد LlamaFlow تلقائيًا ما إذا كان الطلب سيخترق حد الرمز المميز قبل إرسال الطلب الفعلي إلى مزود النموذج (على سبيل المثال Openai). سيؤدي ذلك إلى حفظ مكالمة واحدة حول الرحلات الجولة على الشبكة وتتيح لك التعامل مع هذا النوع من الأخطاء بطريقة سريعة الاستجابة. تتمثل الطريقة المعتادة للتعامل مع هذه الأخطاء في إزالة الرسائل في سجل الرسائل (إذا كنت تستخدم الدردشة مع مجموعة retainMemory ) ، أو تقسيم المحتوى الخاص بك إلى مجموعات أصغر ومعالجتها في طلبات متعددة.
فيما يلي مثال على اصطياد خطأ الفائض الرمزي. لاحظ أنه تم تعيين minimumResponseTokens على قيمة عالية لتشغيل هذا الخطأ بشكل صريح ( gpt-3.5-turbo له حد أقصى سياق قدره 4096 ، وبالتالي فإن تحديد الحد الأدنى إلى 4095 يعني أنه لم يتبق سوى رمز واحد للمطالبة الفعلية ، وهو ما لا يكفي للمثال أدناه.)
try {
// make sure to set the `contextSize` to enable automatic token checking
const model = new OpenAI (
{ apiKey : 'YOUR_OPENAI_KEY' } ,
{ model : 'gpt-3.5-turbo' , contextSize : 4096 } ,
) ;
const chat = model . chat ( {
systemMessage : 'You are an AI assistant' ,
} ) ;
await chat . request (
{ message : 'hello world, testing overflow logic' } ,
{ minimumResponseTokens : 4095 } ,
) ;
} catch ( e ) {
if ( e instanceof TokenError ) {
console . info (
`Caught token overflow, overflowed tokens: ${ e . overflowTokens } ` ,
) ;
}
} تتمثل إحدى الطرق الشائعة في التعامل مع مشكلات الحد من الرمز المميز إلى تقسيم المحتوى الخاص بك. يوفر LlamaFlow طريقة مساعدة مفيدة تلتف طريقة chat.request وسيقوم تلقائيًا بتقسيم النص الخاص بك بناءً على تكوين قطعة إدخال. إنه ذكي بما يكفي لتقسيم النص الخاص بك فقط إذا كان يحدد أنه أعلى من الحد المميز ، وسيحاول الحفاظ على أكبر قدر ممكن من النص الأصلي.
const response = await chat . requestWithSplit (
'hello world, testing overflow logic' ,
( text ) =>
prompt . text ( {
message : `Add other required prompts first, then add your content: ${ text } ` ,
} ) ,
) ; لاحظ أنه الآن ، يتم تقديم المحتوى الرئيسي للمطالبة أولاً. هذا هو المحتوى الذي سيتم تقسيمه بواسطة خائن النص (على طول n . و , و الشخصيات أولا ، لتكوينها). يمكنك إضافة أي مطالبات مطلوبة إضافية ودمجها مع موجه المحتوى في معلمة responseFn .
llamaflow usese وحدة debug لتسجيل الرسائل والخطأ. لتشغيله في وضع التصحيح ، قم بتعيين متغير DEBUG Env:
DEBUG=llamaflow:* yarn playground
يمكنك أيضًا تحديد أنواع تسجيل مختلفة عبر:
DEBUG=llamaflow:error yarn playground DEBUG=llamaflow:log yarn playground
يأتي LlamaFlow أيضًا مع دعم لنماذج Azure Openai. عادةً ما تكون إصدار Azure أسرع بكثير وأكثر موثوقية من نقاط نهاية API الخاصة بـ Openai. من أجل استخدام نقاط نهاية Azure ، يجب أن تتضمن خيارين محددين من Azure عند تهيئة نموذج Openai و azureDeployment و azureEndpoint . سيتم الآن استخدام حقل apiKey لمفتاح Azure API.
يمكنك العثور على مفتاح Azure API ونقطة النهاية في بوابة Azure. يجب إنشاء نشر Azure تحت بوابة Azure AI.
لاحظ أنه سيتم تجاهل المعلمة model في ModelConfig عند استخدام Azure. هذا لأنه في نظام Azure ، يتم اختيار model عند إنشاء النشر ، وليس في وقت التشغيل.
const model = new OpenAI ( {
apiKey : 'AZURE_OPENAI_KEY' ,
azureDeployment : 'AZURE_DEPLOYMENT_NAME' ,
azureEndpoint : 'AZURE_ENDPOINT' ,
} ) ; النموذج الوحيد الذي يدعم LlamaFlow حاليًا هو النماذج القائمة على الدردشة في Openai.
const model = new OpenAI ( openAiConfig , modelConfig ) ; interface OpenAIConfig {
apiKey : string ;
} خريطة تكوين النموذج هذه لتكوين Openai مباشرة ، راجع Doc: https://platform.openai.com/docs/api- Reference/Chat/Create
interface ModelConfig {
model ?: string ;
maxTokens ?: number ;
temperature ?: number ;
topP ?: number ;
stop ?: string | string [ ] ;
presencePenalty ?: number ;
frequencyPenalty ?: number ;
logitBias ?: Record < string , number > ;
user ?: string ;
stream ?: boolean ;
} عندما يتم ضبط stream على true ، يمكنك الوصول إلى مخرجات جزئية لطلبات الطراز من خلال تمريرها في باعث حدث إلى ChatRequestOptions عند تقديم الطلبات. سيتم إرسال المخرجات الجزئية كسلسلة على حدث data .
لتقديم طلب إلى النموذج ، تحتاج أولاً إلى إنشاء الكائن المطري. توفر المطالبات وسيلة لإضافة التحقق من الصحة وإعادة إعادة الصحة إلى كل طلب.
import { prompt } from 'llama-flow' ;
prompt . text ( prompt : string ) ;
prompt . text ( prompt : RawPrompt ) ;
prompt . json ( prompt : JSONPrompt ) ;
prompt . bulletPoints ( prompt : BulletPointsPrompt ) ;
prompt . boolean ( prompt : BooleanPrompt ) ; يمكنك إما الطلب كسلسلة ، أو كقوة RawPrompt .
interface RawPrompt < T = string > {
message : string ;
parse ?: (
response : ChatResponse < string > ,
) => MaybePromise <
{ success : false ; retryPrompt ?: string } | { success : true ; data : T }
> ;
promptRetries ?: number ;
}الرسالة هذا هو النص الذي يتم إرساله إلى النموذج.
Parse يمكنك تنفيذ محلل مخصص من خلال تحديد طريقة parse الخاصة بك.
عند تحديد طريقة parse مخصصة تُرجع نوع بيانات مخصص ، يمكنك إضافة نوع عام إلى RawPrompt ، والذي سيؤدي تلقائيًا إلى إلقاء نوع العائد من parse عام. كما أنه سينشر النوع على طول الطريق من خلال طريقة chat.request .
إذا كانت البيانات التي يتم إرجاعها بواسطة النموذج مشوهة ، فيمكنك إرجاع سلسلة retryPrompt مخصصة ، مما سيؤدي إلى إعادة صياغة النموذج LlamaFlow.
تحدد PrompTretries عدد المرات التي يجب إعادة صياغتها على النموذج قبل أن يرمي الطلب خطأً. الافتراضيات إلى 3. لاحظ أن parse يجب أن يعيد retryPrompt صالحة لأي إعادة محاكمة لمحاولة.
interface BooleanPrompt {
message : string ;
promptRetries ?: number ;
} استخدم موجه هذا إذا كنت تريد طرح سؤال على سؤال حيث تتوقع فقط استجابة true أو false .
رسالة الاستعلام لإرساله إلى النموذج. ستعمل هذه المطالبة تلقائيًا على إلحاق إرشادات التنسيق بالرسالة التي يتم إرسالها إلى النموذج الذي يخبر النموذج لتنسيق رده على أنه منطقية ، بحيث يمكنك فقط تضمين الاستعلام في message ، دون كتابة أي بيانات تنسيق إضافية.
interface BulletPointsPrompt {
message : string ;
amount ?: number ;
length ?: number ;
promptRetries ?: number ;
}استخدم هذه المطالبة إذا كنت تريد أن يقوم النموذج بإرجاع قائمة الأوتار.
رسالة الاستعلام لإرساله إلى النموذج. ستعمل هذه المطالبة تلقائيًا على إلحاق إرشادات التنسيق بالرسالة التي تخبر النموذج كيفية تنسيق الاستجابة.
مقدار عدد نقاط الرصاص التي يجب إرجاعها.
طول الحد الأقصى لعدد الأحرف التي يجب أن تكون في كل نقطة رصاصة.
interface JSONPrompt < T extends z . ZodType > {
message : string ;
schema : T ;
parseResponse ?: ( res : string ) => MaybePromise < z . infer < T > > ;
retryMessage ?: string ;
promptRetries ?: number ;
}رسالة رسالة لإرسالها إلى النموذج. على عكس مطالبات Boolean أو Bullet Point ، لا تقوم هذه المطالبة تلقائيًا بإنشاء تعليمات تكوين للنموذج. لذلك كجزء من رسالتك إلى النموذج ، يجب عليك تضمين تعليمات التنسيق لإرجاع البيانات بتنسيق JSON ، وكذلك شكل JSON.
المخطط هذا هو مخطط Zod الذي سيتم استخدامه لتحليل الاستجابة من النموذج.
ParseResponse إذا طلبت من النموذج عدم إرجاع البيانات بتنسيق JSON ، يمكنك تحديد محلل مخصص لتحليل سلسلة الإرجاع إلى JSON ، قبل إرسالها إلى schema للتحقق من الصحة.
RetryMessage في حالة فشل تحليل المخطط ، سيتم استخدام ذلك كجزء من الرسالة المرسلة إلى النموذج لإعادة الاستجابة المنسقة بشكل صحيح. لاحظ أن هذه المطالبة ستقوم تلقائيًا بإنشاء رسالة RESK اعتمادًا على أخطاء تحليل المخطط (على سبيل المثال ، إذا كان مفتاح معين مفقودًا ، فسيطلب LlamaFlow النموذج أن يتضمن هذا المفتاح المحدد). لذلك هذا الحقل بحت لإعطاء سياق إضافي للنموذج على RESK.
يخزن كائن الدردشة جلسة دردشة مع النموذج. ستهتم الجلسة بتخزين سجل الرسائل ، بحيث يمكنك ببساطة متابعة المحادثة مع النموذج من خلال تقديم طلب آخر.
const chat = model . chat ( config : ChatConfig ) ;الخيارات التي يمكنك تعيين سلوك الاحتفاظ بالذاكرة وكذلك خيارات الطلب الافتراضي لكل طلب يتم إرساله في هذه الدردشة.
export interface ChatConfig {
// the message injected at the start of every chat to steer the agent
systemMessage : string ;
// if chat memory should be retained after every request. when enabled, the chat's behavior will be similar to a normal user chat room, and model can have access to history when making inferences. defaults to false
retainMemory ?: boolean ;
// set default request options. note that this can be overridden on a per-request basis
options ?: ChatRequestOptions ;
} لإرسال طلب إلى جلسة الدردشة:
const res : ChatResponse = await chat . request ( prompt , options : ChatRequestOptions ) ;الخيارات التي يمكنك تجاوزها لخيارات الطلب الافتراضي عبر هذه المعلمة. سيتم إعادة تشغيل الطلب تلقائيًا إذا كان هناك خطأ راتليميت أو خادم.
لاحظ أن إعادة المحاولة في الطلب لا تحسب نحو مطالبة RESK محددة في قسم المطالبة أعلاه.
type ChatRequestOptions = {
// the number of time to retry this request due to rate limit or recoverable API errors
retries ?: number ;
retryInterval ?: number ;
timeout ?: number ;
// the minimum amount of tokens to allocate for the response. if the request is predicted to not have enough tokens, it will automatically throw a 'TokenError' without sending the request
minimumResponseTokens ?: number ;
// override the messages used for completion, only use this if you understand the API well
messages ?: Message [ ] ;
// pass in an event emitter to receive message stream events
events ?: EventEmitter ;
} ; ردود الدردشة هي بالتنسيق التالي:
interface ChatResponse < T = string > {
content : T ;
model : string ;
// set to true if this content was streamed. note to actually access the stream, you have to pass in an event emitter via ChatRequestOptions
isStream : boolean ;
usage : {
promptTokens : number ;
completionTokens : number ;
totalTokens : number ;
} ;
}محتوى محتوى محتوى ومحتوى من المطالبة. سيتم تعيين الأنواع تلقائيًا وفقًا للمطالبة التي استخدمتها.
النموذج النموذج المحدد المستخدم للإكمال (مثل gpt-3.5-turbo-0301 )
بيانات استخدام الرمز المميز ، هذه الخرائط تفتح مباشرة استجابة الاستخدام.
إذا كنت ترغب في إعادة تعيين تاريخ الرسالة في تاريخ الدردشة ، فهناك طريقة مساعد بسيطة:
chat . reset ( ) ;لاحظ أن هذه الطريقة هي فتحة الهروب. من الأفضل فقط إنشاء جلسة دردشة جديدة إذا كنت ترغب في تقديم طلب جديد باستخدام قائمة نظيفة. المنطق المعقد حيث تقوم بإعادة ضبط جلسة الدردشة عدة مرات يمكن أن يصعب تتبعها وصعوبة تصحيحها.
لاحظ أنه إذا كنت ترغب في تجاوز منطق إدارة الدردشة في Llamaflow ، وإرسال طلب إلى طراز الطبقة السفلية مباشرة ، فيمكنك إرسال طلب إلى النموذج مباشرة دون إنشاء دردشة:
const model = new OpenAI ( openAiConfig , modelConfig ) ;
const res = await model . request ( messages : Message [ ] , options : ChatRequestOptions ) ; هذا سيتجاوز أي إدارة سجل الدردشة ، والتنسيق الفوري والتحليل ، وكذلك منطق الشخصية. لا يزال بإمكانك الاستفادة من ميزة إعادة محاكاة API عبر ChatRequestOptions .