استراتيجيات خاصة بالمستندات للبرمجيات البرمجية وHTML
طبّقوا تقسيمًا متخصصًا على شيفرة Python باستخدام مقسّمات الدوال القائمة على AST، وعلى HTML باستخدام محللات واعية بالوسوم، وعلى Markdown باستخدام تسلسل العناوين.
استراتيجيات خاصة بالمستندات للبرمجيات البرمجية وHTML درس مجاني في AI Engineering Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Engineering Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.
لماذا تفشل التجزئة العامة مع المستندات المتخصصة
صُممت التجزئة المعتمدة على النصوص للنثر، لكن البيانات الواقعية تتضمن الشيفرة المصدرية وصفحات HTML ووثائق Markdown. وقد يؤدي تقسيم الشيفرة عند حد ثابت لعدد المحارف إلى قطع دالة في منتصف جسمها، مما يجعل المقطع عديم الفائدة للاسترجاع. تحتاج المستندات المتخصصة إلى مُجزّئات تفهم بنيتها الداخلية، لا طولها فحسب.
تجزئة شيفرة Python المستندة إلى AST
تلتقط شجرة البنية المجردة (AST) لملف Python كل دالة وفئة ووحدة نمطية في صورة عقدة منظمة. ومن خلال اجتياز AST، يمكنك استخراج كل دالة أو method في مقطع مستقل، مع إبقاء التوقيع وسلسلة التوثيق والجسم معًا. تستخدم LangChain هذا الأسلوب داخليًا في PythonCodeTextSplitter.
import ast
import textwrap
def extract_functions(source_code: str) -> list[dict]:
tree = ast.parse(source_code)
chunks = []
for node in ast.walk(tree):
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
start = node.lineno - 1
end = node.end_lineno
lines = source_code.splitlines()[start:end]
chunks.append({
'name': node.name,
'code': '\n'.join(lines),
'start_line': node.lineno,
})
return chunksالتجزئة عند حدود الفئات
في قواعد الشيفرة كائنية التوجه، تكون التجزئة على مستوى الفئة أفضل غالبًا من التجزئة على مستوى الدالة. إذ يحتفظ مقطع الفئة بالعلاقة بين الأساليب والحالة المشتركة التي تعمل عليها. يمكنك تضمين سلسلة توثيق الفئة وأجسام جميع الأساليب في مقطع واحد، ثم إنشاء مقاطع منفصلة أدق للأساليب الطويلة فقط.
from langchain_text_splitters import Language, RecursiveCharacterTextSplitter
python_splitter = RecursiveCharacterTextSplitter.from_language(
language=Language.PYTHON,
chunk_size=1000,
chunk_overlap=100,
)
with open('my_module.py', 'r') as f:
source = f.read()
chunks = python_splitter.create_documents([source])
print(f'Created {len(chunks)} code chunks')إضافة بيانات وصفية للشيفرة إلى المقاطع
لا تكون مقاطع الشيفرة الخام مفيدة إلا بقدر فائدة بياناتها الوصفية. عند تخزين مقاطع الشيفرة في قاعدة بيانات متجهية، أدرج مسار الملف واسم الدالة ولغة البرمجة ونطاق الأسطر. تتيح هذه البيانات الوصفية للمسترجع التصفية حسب اللغة أو الملف، كما تتيح لـ LLM الاستشهاد بالموقع الدقيق للمصدر في إجابته.
from langchain_core.documents import Document
def chunk_python_file(filepath: str) -> list[Document]:
with open(filepath) as f:
source = f.read()
functions = extract_functions(source) # from previous example
docs = []
for fn in functions:
docs.append(Document(
page_content=fn['code'],
metadata={
'source': filepath,
'function': fn['name'],
'language': 'python',
'start_line': fn['start_line'],
}
))
return docsHTML: البنية أهم من المحارف
تتسم مستندات HTML ببنية هرمية تتكون من العناوين والأقسام والفقرات والقوائم. وغالبًا ما يؤدي تقسيم HTML حسب عدد المحارف إلى القطع عبر الوسوم، فتنتج أجزاء مشوهة. والطريقة الصحيحة هي تحليل HTML باستخدام محلل مناسب مثل BeautifulSoup واستخراج عناصر ذات معنى دلالي مثل وسوم <article> و<section> و<p>.
from bs4 import BeautifulSoup
def chunk_html_by_section(html: str) -> list[dict]:
soup = BeautifulSoup(html, 'html.parser')
chunks = []
for tag in soup.find_all(['h1', 'h2', 'h3', 'p', 'li']):
text = tag.get_text(separator=' ', strip=True)
if len(text) > 40: # skip trivial fragments
chunks.append({
'tag': tag.name,
'text': text,
})
return chunksتجزئة HTML الهرمية حسب العناوين
تجمع استراتيجية HTML الأكثر تطورًا المحتوى ضمن أقرب عنوان إليه. فكل فقرة وقائمة تأتي بعد عنوان <h2> تنتمي إلى ذلك القسم. ومن خلال جمع النص مع عنوانه الأب، تحافظ على سياق الموضوع الذي كانت الفقرة المستقلة ستفقده لولا ذلك. تطبّق LangChain هذا تلقائيًا باستخدام HTMLHeaderTextSplitter.
from langchain_text_splitters import HTMLHeaderTextSplitter
headers_to_split_on = [
('h1', 'Header 1'),
('h2', 'Header 2'),
('h3', 'Header 3'),
]
splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
with open('page.html') as f:
html = f.read()
sections = splitter.split_text(html)
for sec in sections[:3]:
print(sec.metadata)
print(sec.page_content[:200])
print('---')Markdown: الحفاظ على التسلسل الهرمي للعناوين
تُنظم وثائق Markdown باستخدام العناوين # و## و###. وتُجزّئ MarkdownHeaderTextSplitter المحتوى عند حدود العناوين، وتخزن التسلسل الهرمي للعناوين في البيانات الوصفية. وهذا يعني أن كل مقطع يعرف مسار عناوينه الكامل، مما يحسّن بدرجة كبيرة صلة السياق المسترجع عندما يسأل المستخدمون عن أقسام محددة من الوثائق.
from langchain_text_splitters import MarkdownHeaderTextSplitter
headers_to_split_on = [
('#', 'H1'),
('##', 'H2'),
('###', 'H3'),
]
md_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
with open('README.md') as f:
markdown = f.read()
docs = md_splitter.split_text(markdown)
for doc in docs[:2]:
print('Metadata:', doc.metadata)
print('Content:', doc.page_content[:300])
print()التجزئة الثانوية بعد التجزئة حسب العناوين
بعد التجزئة حسب العنوان، قد تظل الأقسام الفردية طويلة جدًا بالنسبة إلى حد الرموز في نموذج التضمين لديك. والنمط الموصى به هو التجزئة على خطوتين: ابدأ بالتجزئة وفق التسلسل الهرمي للعناوين للحفاظ على السياق الدلالي، ثم طبّق مُجزّئًا قائمًا على المحارف على أي قسم يتجاوز حد حجم المقطع. يضمن ذلك ألا يكون أي مقطع كبيرًا جدًا، مع الحفاظ على البيانات الوصفية للعناوين.
from langchain_text_splitters import MarkdownHeaderTextSplitter, RecursiveCharacterTextSplitter
header_splitter = MarkdownHeaderTextSplitter(
headers_to_split_on=[('#', 'H1'), ('##', 'H2')]
)
char_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
)
with open('docs.md') as f:
md = f.read()
header_chunks = header_splitter.split_text(md)
final_chunks = char_splitter.split_documents(header_chunks)
print(f'{len(final_chunks)} final chunks produced')تجزئة ملفات PDF مع مراعاة الجداول
غالبًا ما تفقد ملفات PDF المستخرجة باستخدام أدوات مثل PyMuPDF أو pdfplumber بنية الجداول، فتنتج صفوفًا نصية مشوهة. ولمعالجة ذلك، استخدم محللات PDF تراعي التخطيط وتكتشف الحدود المحيطة بالجداول، ثم تحولها إلى تنسيق Markdown أو CSV قبل التجزئة. تعامل مع كل جدول باعتباره مقطعًا واحدًا ذي بيانات وصفية منظمة تحدد أنه جدول وليس نصًا نثريًا.
import pdfplumber
def extract_pdf_chunks(pdf_path: str) -> list[dict]:
chunks = []
with pdfplumber.open(pdf_path) as pdf:
for page_num, page in enumerate(pdf.pages):
# Extract tables separately
for table in page.extract_tables():
rows = ['|'.join(str(c) for c in row) for row in table]
chunks.append({
'type': 'table',
'content': '\n'.join(rows),
'page': page_num + 1,
})
# Extract prose text
text = page.extract_text()
if text:
chunks.append({'type': 'text', 'content': text, 'page': page_num + 1})
return chunksاكتشاف اللغة للمجموعات المختلطة
غالبًا ما تخلط قواعد المعرفة المؤسسية بين أنواع مختلفة من الملفات: نصوص Python البرمجية، ووثائق API بتنسيق HTML، وملاحظات البنية المعمارية بتنسيق Markdown، وعمليات تصدير البيانات بتنسيق CSV. ينبغي أن يعمل مسار تجزئة متين على اكتشاف نوع الملف من الامتداد أو نوع MIME، ثم يوجه كل مستند إلى مُجزّئ متخصص مناسب. ويمنع ذلك تطبيق منطق تجزئة الشيفرة على النثر أو العكس.
from pathlib import Path
def route_document(filepath: str) -> list[dict]:
ext = Path(filepath).suffix.lower()
if ext == '.py':
return chunk_python_file(filepath)
elif ext in ('.html', '.htm'):
with open(filepath) as f:
return chunk_html_by_section(f.read())
elif ext == '.md':
# use MarkdownHeaderTextSplitter
return chunk_markdown(filepath)
elif ext == '.pdf':
return extract_pdf_chunks(filepath)
else:
# fallback: plain text recursive splitter
return chunk_plain_text(filepath)الحفاظ على السياق باستخدام الأسطر المحيطة
عند تجزئة الشيفرة حسب الدالة، يكون من المفيد غالبًا تضمين بضعة أسطر من السياق المحيط، مثل عبارات الاستيراد في أعلى الملف أو تعريف الفئة التي تتضمن أسلوبًا. يساعد هذا السياق LLM على فهم المكتبات المتاحة ودور الدالة ضمن الفئة الأوسع، مما يحسّن جودة الإجابات المُنشأة.
def chunk_with_imports(source_code: str, fn_node, lines: list[str]) -> str:
# Gather top-of-file imports (first block before first non-import)
import_lines = []
for line in lines:
stripped = line.strip()
if stripped.startswith('import ') or stripped.startswith('from '):
import_lines.append(line)
elif stripped and not stripped.startswith('#'):
break
fn_body = '\n'.join(lines[fn_node.lineno - 1:fn_node.end_lineno])
return '\n'.join(import_lines) + '\n\n' + fn_bodyتحقق سريع
اختبر مدى فهمك لاستراتيجيات التجزئة الخاصة بالمستندات من هذا الدرس.
مراجعة الدرس
تعلمت في هذا الدرس أن: التجزئة المستندة إلى AST تحافظ على حدود دوال وفئات Python، وأن HTMLHeaderTextSplitter وMarkdownHeaderTextSplitter يحترمان التسلسل الهرمي للعناوين للحفاظ على السياق مع قسمه، وأن النهج ذي الخطوتين (التجزئة حسب العنوان ثم التجزئة حسب المحارف) يتعامل مع الأقسام كبيرة الحجم دون فقدان البيانات الوصفية البنيوية. بعد ذلك سنستكشف البحث الهجين الذي يجمع بين الاسترجاع الكثيف والمتناثر.
الأسئلة الشائعة
هل درس «استراتيجيات خاصة بالمستندات للبرمجيات البرمجية وHTML» مجاني؟
نعم — نص درس «استراتيجيات خاصة بالمستندات للبرمجيات البرمجية وHTML» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Engineering Academy، انتقل إلى CoddyKit PRO. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.
ماذا ستتعلم في «استراتيجيات خاصة بالمستندات للبرمجيات البرمجية وHTML»؟
طبّقوا تقسيمًا متخصصًا على شيفرة Python باستخدام مقسّمات الدوال القائمة على AST، وعلى HTML باستخدام محللات واعية بالوسوم، وعلى Markdown باستخدام تسلسل العناوين. تتمرن على AI Engineering Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ AI Engineering Academy؟
لا تُشترط خبرة سابقة. AI Engineering Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «استراتيجيات خاصة بالمستندات للبرمجيات البرمجية وHTML»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس AI Engineering Academy هذا؟
نعم. كل درس في AI Engineering Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- لماذا يضر التقسيم الساذج بالاسترجاع
- التقسيم الدلالي باستخدام تشابه التضمينات
- الاسترجاع من الأبناء إلى الآباء ومن الصغير إلى الكبير
- استراتيجيات خاصة بالمستندات للبرمجيات البرمجية وHTML