تقنية وتكنولوجيا

دليل المبتدئين لبناء تطبيق الجيل المعزز للاسترجاع (RAG) من الصفر


تعلم المعرفة المهمة لبناء تطبيقات الذكاء الاصطناعي، باللغة الإنجليزية البسيطة

نحو علم البيانات

أصبح الجيل المعزز للاسترجاع، أو RAG، رائجًا هذه الأيام لأنه يقدم بعض القدرات الجادة لنماذج اللغات الكبيرة مثل OpenAI’s GPT-4 – وهي القدرة على استخدام البيانات الخاصة بها والاستفادة منها.

سيعلمك هذا المنشور الحدس الأساسي وراء RAG مع توفير برنامج تعليمي بسيط لمساعدتك على البدء.

هناك الكثير من الضجيج في مجال الذكاء الاصطناعي وخاصة فيما يتعلق بـ RAG. يحاول البائعون المبالغة في تعقيد الأمر. إنهم يحاولون حقن أدواتهم، وأنظمتهم البيئية، ورؤيتهم.

إنه يجعل طريقة RAG أكثر تعقيدًا مما يجب. تم تصميم هذا البرنامج التعليمي لمساعدة المبتدئين على تعلم كيفية إنشاء تطبيقات RAG من البداية. لا يوجد زغب، ولا مصطلحات (حسنًا، الحد الأدنى)، ولا مكتبات، مجرد تطبيق RAG بسيط خطوة بخطوة.

يدعو جيري من LlamaIndex إلى بناء الأشياء من الصفر لفهم القطع حقًا. بمجرد القيام بذلك، فإن استخدام مكتبة مثل LlamaIndex يصبح أكثر منطقية.

يمكنك البناء من الصفر لتتعلم، ثم البناء باستخدام المكتبات لتوسيع نطاقها.

هيا بنا نبدأ!

ربما تكون قد سمعت أو لم تسمع عن الجيل المعزز للاسترجاع أو RAG.

فيما يلي التعريف من منشور المدونة الذي يقدم المفهوم من Facebook:

يعد بناء نموذج يبحث ويضع سياقًا أكثر صعوبة، ولكنه ضروري للتقدم المستقبلي. لقد حققنا مؤخرًا تقدمًا كبيرًا في هذا المجال من خلال بنية الجيل المعزز للاسترجاع (RAG)، وهو نموذج قابل للتمييز من طرف إلى طرف يجمع بين مكون استرجاع المعلومات (نظام استرجاع المرور الكثيف الخاص بـ Facebook AI) مع مولد seq2seq (ثنائي الاتجاه والتلقائي الخاص بنا -المحولات الرجعية [BART] نموذج). يمكن ضبط RAG بدقة على المهام النهائية كثيفة المعرفة لتحقيق أحدث النتائج مقارنة حتى بأكبر نماذج اللغات seq2seq المدربة مسبقًا. وعلى عكس هذه النماذج المدربة مسبقًا، يمكن تغيير المعرفة الداخلية لـ RAG بسهولة أو حتى استكمالها بسرعة، مما يمكّن الباحثين والمهندسين من التحكم في ما يعرفه RAG وما لا يعرفه دون إضاعة الوقت أو إعادة تدريب القوة الحسابية للنموذج بأكمله.

واو، هذا الفم.

لتبسيط التقنية للمبتدئين، يمكننا أن نذكر أن جوهر RAG يتضمن إضافة بياناتك الخاصة (عبر أداة استرجاع) إلى الموجه الذي تقوم بتمريره إلى نموذج لغة كبير. ونتيجة لذلك، تحصل على الإخراج. ويمنحك ذلك فوائد عديدة:

  1. يمكنك تضمين الحقائق في الموجه لمساعدة LLM على تجنب الهلوسة
  2. يمكنك (يدويًا) الرجوع إلى مصادر الحقيقة عند الرد على استعلام المستخدم، مما يساعد على التحقق من أي مشكلات محتملة.
  3. يمكنك الاستفادة من البيانات التي ربما لم يتم تدريب LLM عليها.
  1. مجموعة من الوثائق (تسمى رسميًا مجموعة)
  2. مدخل من المستخدم
  3. مقياس التشابه بين مجموعة الوثائق ومدخلات المستخدم

نعم، الأمر بهذه البساطة.

لبدء التعلم وفهم الأنظمة المستندة إلى RAG، لا تحتاج إلى متجر متجهات، حتى أنك لا تحتاج إليها يحتاج LLM (على الأقل للتعلم والفهم من الناحية المفاهيمية).

على الرغم من أن الأمر غالبًا ما يتم تصويره على أنه معقد، إلا أنه ليس من الضروري أن يكون كذلك.

سنقوم بالخطوات التالية بالتسلسل

  1. تلقي إدخال المستخدم
  2. تنفيذ قياس التشابه لدينا
  3. قم بالمعالجة اللاحقة لإدخال المستخدم والوثيقة (المستندات) التي تم جلبها.

تتم المعالجة اللاحقة باستخدام LLM.

من الواضح أن ورقة RAG الفعلية ال الموارد. المشكلة هي أنها تفترض الكثير من السياق. الأمر أكثر تعقيدًا مما نحتاج إليه.

على سبيل المثال، إليك نظرة عامة على نظام RAG كما هو مقترح في الورقة.

نظرة عامة على RAG من ورقة RAG التي أعدها لويس وآخرون

هذا كثيف.

إنه أمر رائع بالنسبة للباحثين ولكن بالنسبة لبقيتنا، سيكون من الأسهل كثيرًا التعلم خطوة بخطوة من خلال بناء النظام بأنفسنا.

دعنا نعود إلى بناء RAG من الصفر، خطوة بخطوة. إليك الخطوات المبسطة التي سنعمل عليها. على الرغم من أن هذا ليس “RAG” من الناحية الفنية، إلا أنه نموذج مبسط جيد للتعلم به ويسمح لنا بالتقدم إلى أشكال أكثر تعقيدًا.

أدناه يمكنك أن ترى أن لدينا مجموعة بسيطة من “المستندات” (يرجى أن تكون كريمًا 😉).

corpus_of_documents = [
"Take a leisurely walk in the park and enjoy the fresh air.",
"Visit a local museum and discover something new.",
"Attend a live music concert and feel the rhythm.",
"Go for a hike and admire the natural scenery.",
"Have a picnic with friends and share some laughs.",
"Explore a new cuisine by dining at an ethnic restaurant.",
"Take a yoga class and stretch your body and mind.",
"Join a local sports league and enjoy some friendly competition.",
"Attend a workshop or lecture on a topic you're interested in.",
"Visit an amusement park and ride the roller coasters."
]

الآن نحن بحاجة إلى وسيلة لقياس التشابه بين إدخال المستخدم ونحن في طريقنا لتلقي و مجموعة من الوثائق التي قمنا بتنظيمها. يمكن القول إن أبسط مقياس للتشابه هو تشابه الجاكار. لقد كتبت عن ذلك في الماضي (راجع هذا المنشور ولكن الإجابة المختصرة هي أن تشابه الجاكار هو التقاطع مقسومًا على اتحاد “مجموعات” الكلمات.

يتيح لنا ذلك مقارنة مدخلات المستخدم لدينا مع المستندات المصدر.

ملاحظة جانبية: المعالجة المسبقة

التحدي هو أنه إذا كان لدينا سلسلة بسيطة مثل "Take a leisurely walk in the park and enjoy the fresh air.",، سيتعين علينا معالجة ذلك مسبقًا في مجموعة، حتى نتمكن من إجراء هذه المقارنات. سنقوم بذلك بأبسط طريقة ممكنة، بأحرف صغيرة وتقسيمها " ".

def jaccard_similarity(query, document):
query = query.lower().split(" ")
document = document.lower().split(" ")
intersection = set(query).intersection(set(document))
union = set(query).union(set(document))
return len(intersection)/len(union)

نحن الآن بحاجة إلى تحديد وظيفة تأخذ الاستعلام الدقيق ومجموعتنا وتختار المستند “الأفضل” لإعادته إلى المستخدم.

def return_response(query, corpus):
similarities = []
for doc in corpus:
similarity = jaccard_similarity(query, doc)
similarities.append(similarity)
return corpus_of_documents[similarities.index(max(similarities))]

الآن يمكننا تشغيله، وسنبدأ بمطالبة بسيطة.

user_prompt = "What is a leisure activity that you like?"

وإدخال مستخدم بسيط …

user_input = "I like to hike"

والآن يمكننا أن نعيد ردنا.

return_response(user_input, corpus_of_documents)
'Go for a hike and admire the natural scenery.'

تهانينا، لقد قمت بإنشاء تطبيق RAG أساسي.

لدي 99 مشكلة والتشابه السيئ هو واحد

لقد اخترنا الآن مقياس تشابه بسيط للتعلم. لكن هذا سيكون مشكلة لأنه بسيط للغاية. ليس لديها فكرة عن دلالات. إنها تنظر فقط إلى الكلمات الموجودة في كلا الوثيقتين. وهذا يعني أننا إذا قدمنا ​​مثالًا سلبيًا، فسنحصل على نفس “النتيجة” لأن هذا هو المستند الأقرب.

user_input = "I don't like to hike"
return_response(user_input, corpus_of_documents)
'Go for a hike and admire the natural scenery.'

هذا هو الموضوع الذي سيتم طرحه كثيرًا مع “RAG”، ولكن في الوقت الحالي، كن مطمئنًا إلى أننا سنعالج هذه المشكلة لاحقًا.

في هذه المرحلة، لم نقم بأي معالجة لاحقة لـ “الوثيقة” التي نرد عليها. حتى الآن، قمنا بتنفيذ جزء “الاسترجاع” فقط من “جيل الاسترجاع المعزز”. والخطوة التالية هي زيادة التوليد من خلال دمج نموذج اللغة الكبير (LLM).

للقيام بذلك، سنستخدم ollama لبدء العمل باستخدام LLM مفتوح المصدر على أجهزتنا المحلية. يمكننا بسهولة استخدام gpt-4 الخاص بـ OpenAI أو Anthropic’s Claude ولكن في الوقت الحالي، سنبدأ باستخدام llama2 مفتوح المصدر من Meta AI.

ستفترض هذه المقالة بعض المعرفة الأساسية بنماذج اللغات الكبيرة، لذا دعونا ننتقل مباشرة إلى الاستعلام عن هذا النموذج.

import requests
import json

أولا سنقوم بتعريف المدخلات. للعمل مع هذا النموذج، سنأخذ

  1. إدخال المستخدم،
  2. إحضار المستند الأكثر تشابهًا (كما تم قياسه بواسطة مقياس التشابه الخاص بنا)،
  3. قم بتمرير ذلك إلى موجه إلى نموذج اللغة،
  4. ثم إرجاع النتيجة للمستخدم

وهذا يقدم مصطلحًا جديدًا، وهو اِسْتَدْعَى. باختصار، إنها التعليمات التي تقدمها إلى LLM.

عند تشغيل هذا الكود، سترى نتيجة البث. البث مهم لتجربة المستخدم.

user_input = "I like to hike"
relevant_document = return_response(user_input, corpus_of_documents)
full_response = []
prompt = """
You are a bot that makes recommendations for activities. You answer in very short sentences and do not include extra information.
This is the recommended activity: {relevant_document}
The user input is: {user_input}
Compile a recommendation to the user based on the recommended activity and the user input.
"""

بعد أن قمنا بتعريف ذلك، فلنقم الآن باستدعاء واجهة برمجة التطبيقات (API) لـ ollama (و llama2). إحدى الخطوات المهمة هي التأكد من تشغيل ollama بالفعل على جهازك المحلي عن طريق التشغيل ollama serve.

ملحوظة: قد يكون هذا بطيئًا على جهازك، ولكنه بالتأكيد بطيء على جهازك. كن صبورا أيها الجندب الصغير.

url="http://localhost:11434/api/generate"
data = {
"model": "llama2",
"prompt": prompt.format(user_input=user_input, relevant_document=relevant_document)
}
headers = {'Content-Type': 'application/json'}
response = requests.post(url, data=json.dumps(data), headers=headers, stream=True)
try:
count = 0
for line in response.iter_lines():
# filter out keep-alive new lines
# count += 1
# if count % 5== 0:
# print(decoded_line['response']) # print every fifth token
if line:
decoded_line = json.loads(line.decode('utf-8'))

full_response.append(decoded_line['response'])
finally:
response.close()
print(''.join(full_response))

Great! Based on your interest in hiking, I recommend trying out the nearby trails for a challenging and rewarding experience with breathtaking views Great! Based on your interest in hiking, I recommend checking out the nearby trails for a fun and challenging adventure.

وهذا يمنحنا تطبيق RAG كاملاً، من الصفر، بدون مقدمي خدمات، ولا خدمات. أنت تعرف كافة المكونات الموجودة في تطبيق الجيل المعزز للاسترجاع. بصريًا، هذا ما قمنا ببنائه.

سوف يتعامل LLM (إذا كنت محظوظًا) مع إدخالات المستخدم التي تتعارض مع المستند الموصى به. يمكننا أن نرى ذلك أدناه.

user_input = "I don't like to hike"
relevant_document = return_response(user_input, corpus_of_documents)
# https://github.com/jmorganca/ollama/blob/main/docs/api.md
full_response = []
prompt = """
You are a bot that makes recommendations for activities. You answer in very short sentences and do not include extra information.
This is the recommended activity: {relevant_document}
The user input is: {user_input}
Compile a recommendation to the user based on the recommended activity and the user input.
"""
url="http://localhost:11434/api/generate"
data = {
"model": "llama2",
"prompt": prompt.format(user_input=user_input, relevant_document=relevant_document)
}
headers = {'Content-Type': 'application/json'}
response = requests.post(url, data=json.dumps(data), headers=headers, stream=True)
try:
for line in response.iter_lines():
# filter out keep-alive new lines
if line:
decoded_line = json.loads(line.decode('utf-8'))
# print(decoded_line['response']) # uncomment to results, token by token
full_response.append(decoded_line['response'])
finally:
response.close()
print(''.join(full_response))
Sure, here is my response:

Try kayaking instead! It's a great way to enjoy nature without having to hike.

إذا عدنا إلى مخططنا الخاص بتطبيق RAG وفكرنا في ما قمنا ببنائه للتو، فسنرى فرصًا متعددة للتحسين. هذه الفرص هي التي يتم فيها استخدام أدوات مثل مخازن المتجهات والتضمين و”الهندسة” السريعة.

فيما يلي عشرة مجالات محتملة يمكننا من خلالها تحسين الإعداد الحالي:

  1. عدد الوثائق 👉 المزيد من المستندات قد يعني المزيد من التوصيات.
  2. عمق/حجم المستندات 👉 قد يكون المحتوى عالي الجودة والمستندات الأطول التي تحتوي على مزيد من المعلومات أفضل.
  3. عدد الوثائق التي نقدمها إلى LLM 👉 في الوقت الحالي، نمنح شهادة LLM مستندًا واحدًا فقط. يمكننا تغذية العديد منها باعتبارها “سياقًا” والسماح للنموذج بتقديم توصية أكثر تخصيصًا بناءً على مدخلات المستخدم.
  4. أجزاء المستندات التي نقدمها إلى LLM 👉 إذا كان لدينا مستندات أكبر أو أكثر شمولاً، فقد نرغب فقط في إضافة أجزاء من تلك المستندات، أو أجزاء من مستندات مختلفة، أو بعض الاختلافات فيها. وهذا ما يسمى في المعجم بالقطع.
  5. أداة تخزين المستندات لدينا 👉 قد نقوم بتخزين مستنداتنا بطريقة مختلفة أو بقاعدة بيانات مختلفة. على وجه الخصوص، إذا كان لدينا الكثير من المستندات، فقد نستكشف تخزينها في بحيرة بيانات أو مخزن متجه.
  6. مقياس التشابه 👉 إن الطريقة التي نقيس بها التشابه هي نتيجة لذلك، فقد نحتاج إلى مقايضة الأداء والدقة (على سبيل المثال، النظر في كل مستند على حدة).
  7. المعالجة المسبقة للمستندات وإدخال المستخدم 👉 قد نقوم بإجراء بعض المعالجة المسبقة الإضافية أو زيادة مدخلات المستخدم قبل تمريرها إلى مقياس التشابه. على سبيل المثال، قد نستخدم التضمين لتحويل هذا الإدخال إلى متجه.
  8. مقياس التشابه 👉 يمكننا تغيير مقياس التشابه لجلب مستندات أفضل أو أكثر صلة.
  9. الموديل 👉 يمكننا تغيير النموذج النهائي الذي نستخدمه. نحن نستخدم llama2 أعلاه، ولكن يمكننا بسهولة استخدام نموذج إنساني أو نموذج كلود.
  10. المطالبة 👉 يمكننا استخدام موجه مختلف في LLM/النموذج وضبطه وفقًا للإخراج الذي نريد الحصول على الإخراج الذي نريده.
  11. إذا كنت قلقًا بشأن المخرجات الضارة أو السامة 👉 يمكننا تنفيذ نوع من “قاطع الدائرة الكهربائية” الذي يقوم بتشغيل مدخلات المستخدم لمعرفة ما إذا كانت هناك مناقشات سامة أو ضارة أو خطيرة. على سبيل المثال، في سياق الرعاية الصحية، يمكنك معرفة ما إذا كانت المعلومات تحتوي على لغات غير آمنة والاستجابة وفقًا لذلك – خارج التدفق النموذجي.

لا يقتصر نطاق التحسينات على هذه النقاط؛ الاحتمالات واسعة، وسوف نتعمق فيها في الدروس المستقبلية. وحتى ذلك الحين، لا تتردد في ذلك تواصل معنا على تويتر إذا كان لديك أية أسئلة. سعيد الغضب :).

تم نشر هذا المنشور في الأصل على learnbybuilding.ai. أقوم بإجراء دورة تدريبية حول كيفية إنشاء منتجات ذكاء اصطناعي إبداعية لمديري المنتجات في الأشهر المقبلة. سجل هنا.



اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

زر الذهاب إلى الأعلى