{"id":497374,"date":"2026-10-05T10:46:43","date_gmt":"2026-10-05T10:46:43","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=497374"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2026-10-05T10:46:43","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=497374","title":{"rendered":"boilerplate_ratio = 1.73: \u0447\u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0430\u0443\u0434\u0438\u0442\u043e\u0440 \u0433\u043e\u0442\u043e\u0432\u043d\u043e\u0441\u0442\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u043a \u043e\u0442\u0432\u0435\u0442\u0430\u043c \u0418\u0418"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043a\u043b\u0430\u0441\u0441\u0430 GEO (\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u043f\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u044b \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439) \u0432\u044b\u0434\u0430\u044e\u0442 \u0431\u0430\u043b\u043b \u043e\u0442 0 \u0434\u043e 100 \u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439. \u0411\u0430\u043b\u043b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0430\u043a \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0435 \u0438 \u0443\u0435\u0437\u0436\u0430\u0435\u0442 \u0432 \u0442\u0438\u043a\u0435\u0442\u044b \u0438 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b.<\/p>\n<p>\u042f \u0432\u0437\u044f\u043b \u043e\u0434\u0438\u043d \u0442\u0430\u043a\u043e\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, <code>geo-optimizer-skill<\/code> (<a href=\"https:\/\/pypi.org\/project\/geo-optimizer-skill\/\" rel=\"noopener nofollow\">PyPI<\/a>, MIT, \u0430\u0432\u0442\u043e\u0440 Juan Camilo Auriti, \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 <a href=\"https:\/\/github.com\/auriti-labs\/geo-optimizer-skill\" rel=\"noopener nofollow\">auriti-labs\/geo-optimizer-skill<\/a>), CLI \u0432\u0435\u0440\u0441\u0438\u0438 4.18.2, \u0438 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b, \u0438\u0437 \u0447\u0435\u0433\u043e \u0431\u0430\u043b\u043b \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f. \u041f\u043e\u0432\u043e\u0434\u043e\u043c \u0441\u0442\u0430\u043b \u0431\u0430\u0442\u0447: \u043f\u0440\u043e\u0433\u043e\u043d \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u0434\u0435\u0441\u044f\u0442\u043a\u0430\u043c \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0432\u0435\u0440\u043d\u0443\u043b \u043d\u0443\u043b\u0438 \u043f\u043e \u0432\u0441\u0435\u043c. \u042f \u043f\u043e\u043b\u0435\u0437 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u043a\u0430\u043a \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u043b\u044c, \u0438 \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u0447\u0438\u0442\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<p>\u041f\u0435\u0440\u0432\u043e\u0435, \u0447\u0442\u043e \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u043f\u043e \u0434\u043e\u0440\u043e\u0433\u0435: \u043c\u0435\u0442\u0440\u0438\u043a\u0430 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u00ab\u0434\u043e\u043b\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u00bb \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 1.73 \u043d\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435 \u0438\u0437 \u043c\u0435\u043d\u044e, \u043e\u0434\u043d\u043e\u0433\u043e \u0430\u0431\u0437\u0430\u0446\u0430 \u0438 \u043f\u043e\u0434\u0432\u0430\u043b\u0430. \u041a\u043e\u0434 \u0432 \u043d\u0430\u0445\u043e\u0434\u043a\u0435 1, \u0432\u044b\u0432\u043e\u0434 \u0434\u043e\u0441\u043b\u043e\u0432\u043d\u043e \u0442\u0430\u043a\u043e\u0439.<\/p>\n<pre><code>\u043c\u0438\u043d\u0438: \u043f\u0430\u043a\u0435\u0442 ratio 1.73, \u0444\u043b\u0430\u0433 True | \u043f\u0440\u0430\u0432\u043a\u0430 ratio 0.87, \u0444\u043b\u0430\u0433 True | \u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442 60 \u0437\u043d\u0430\u043a\u043e\u0432<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper\"><\/span><\/a><\/div><\/pre>\n<p>\u041e\u0434\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u043f\u0430\u043a\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 robots.txt, llms.txt \u0438 \u0447\u0435\u0442\u044b\u0440\u0435 \u0442\u043e\u0447\u043a\u0438 AI-\u0434\u0438\u0441\u043a\u0430\u0432\u0435\u0440\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u043d\u0430\u0447\u0435 \u0441\u043c\u043e\u0442\u0440\u0438\u0448\u044c \u0440\u0443\u043a\u0430\u043c\u0438 \u043f\u043e \u043e\u0434\u043d\u043e\u0439, \u0430 \u043a\u043e\u0434 \u0440\u0430\u0437\u043b\u043e\u0436\u0435\u043d \u043f\u043e \u0444\u0430\u0439\u043b\u0443 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443, \u0442\u0430\u043a \u0447\u0442\u043e \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u043e\u0447\u043d\u043e. \u041d\u0438\u0436\u0435 \u0448\u0435\u0441\u0442\u044c \u043c\u0435\u0441\u0442, \u0433\u0434\u0435 \u043d\u0430\u043f\u0435\u0447\u0430\u0442\u0430\u043d\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0437\u043d\u0430\u0447\u0438\u0442 \u043d\u0435 \u0442\u043e, \u0447\u0442\u043e \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0441 \u0445\u043e\u0434\u0443, \u0438 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e \u043f\u043e\u0447\u0438\u043d\u043a\u0435 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0435. \u0420\u0430\u0437\u0431\u043e\u0440 \u043d\u0443\u0436\u0435\u043d, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u043a\u0430\u043a\u0443\u044e \u0438\u043c\u0435\u043d\u043d\u043e \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443 \u0432\u044b \u0447\u0438\u0442\u0430\u0435\u0442\u0435.<\/p>\n<h3>\u041a\u0430\u043a \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438<\/h3>\n<p>\u041f\u0430\u043a\u0435\u0442 \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044f \u043a\u0430\u043a \u0443\u0442\u0438\u043b\u0438\u0442\u0430, \u0444\u0430\u0439\u043b\u044b \u043b\u0435\u0436\u0430\u0442 \u0432 \u0435\u0451 venv:<\/p>\n<pre><code class=\"bash\">uv tool install \"geo-optimizer-skill[mcp]\"PY=$(uv tool dir)\/geo-optimizer-skill\/bin\/pythonGEO=$($PY -c 'import geo_optimizer, pathlib; print(pathlib.Path(geo_optimizer.__file__).parent)')ls $GEO   # cli core i18n mcp models skills utils web, \u043f\u043b\u044e\u0441 __init__.py, py.typed, __pycache__<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432 <code>core\/<\/code>, \u043f\u043e \u0444\u0430\u0439\u043b\u0443 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443; \u0432\u0435\u0441\u0430 \u0438 \u043f\u043e\u0440\u043e\u0433\u0438 \u0432 <code>models\/config.py<\/code>, \u0441\u0431\u043e\u0440\u043a\u0430 \u0431\u0430\u043b\u043b\u0430 \u0432 <code>core\/scoring.py<\/code>. \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043d\u0438\u0436\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0438\u0441\u044c \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c <code>$PY<\/code> (3.11.13): \u0432 \u0435\u0433\u043e venv \u0443\u0436\u0435 \u0441\u0442\u043e\u044f\u0442 <code>beautifulsoup4<\/code> 4.15.0 \u0438 <code>httpx<\/code> 0.28.1. \u0417\u0430\u043c\u0435\u0440\u044b \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0441\u0434\u0435\u043b\u0430\u043d\u044b 02.10.2026.<\/p>\n<h3>\u041d\u0430\u0445\u043e\u0434\u043a\u0430 1: \u0434\u043e\u043b\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u044b\u0432\u0430\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u0435\u0434\u0438\u043d\u0438\u0446\u044b<\/h3>\n<p><code>core\/audit_negative.py<\/code>, \u0446\u0438\u0442\u0430\u0442\u0430 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0430, \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u0443\u0431\u0440\u0430\u043d\u044b (\u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0441\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f):<\/p>\n<pre><code class=\"python\">main_content = text_soup.find(\"main\") or text_soup.find(\"article\") or text_soup.find(attrs={\"role\": \"main\"})if main_content and total_text_len &gt; 0:    result.boilerplate_ratio = round(1.0 - (main_text_len \/ total_text_len), 2)elif total_text_len &gt; 0:    nav_footer_len = 0    for tag in text_soup.find_all([\"nav\", \"footer\", \"header\"]):        nav_footer_len += len(tag.get_text(separator=\" \", strip=True))    if nav_footer_len &gt; 0:        result.boilerplate_ratio = round(nav_footer_len \/ total_text_len, 2)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0412\u0435\u0442\u043a\u0438 \u0441\u0447\u0438\u0442\u0430\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0432\u0435\u0449\u0438. \u041b\u0435\u043d\u0434\u043c\u0430\u0440\u043a (<code>main<\/code>, <code>article<\/code>, <code>role=\"main\"<\/code>) \u043d\u0430\u0439\u0434\u0435\u043d: \u0434\u043e\u043b\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u044d\u0442\u043e \u00ab\u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442 \u043c\u0438\u043d\u0443\u0441 \u0442\u0435\u043a\u0441\u0442 \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a\u0430\u00bb. \u041b\u0435\u043d\u0434\u043c\u0430\u0440\u043a\u0430 \u043d\u0435\u0442: \u044d\u0442\u043e \u0441\u0443\u043c\u043c\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432\u0441\u0435\u0445 <code>nav<\/code>, <code>footer<\/code>, <code>header<\/code>, \u0434\u0435\u043b\u0451\u043d\u043d\u0430\u044f \u043d\u0430 \u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.<\/p>\n<p>\u0412\u0442\u043e\u0440\u0430\u044f \u0432\u0435\u0442\u043a\u0430 \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043e\u043b\u0435\u0439 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f. <code>find_all([\"nav\", \"footer\", \"header\"])<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438 <code>header<\/code>, \u0438 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0439 \u0432 \u043d\u0435\u0433\u043e <code>nav<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0435\u043a\u0441\u0442 \u043c\u0435\u043d\u044e \u0432\u0445\u043e\u0434\u0438\u0442 \u0432 \u0441\u0443\u043c\u043c\u0443 \u0434\u0432\u0430\u0436\u0434\u044b. \u041f\u043e\u0442\u043e\u043b\u043a\u0430 \u043d\u0435\u0442, \u0430 <code>boilerplate_high<\/code> \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443 \u0441 <code>BOILERPLATE_RATIO_THRESHOLD = 0.6<\/code>. \u0424\u043b\u0430\u0433 \u0438\u0434\u0451\u0442 \u0432 <code>signals_found<\/code>, \u0442\u043e\u0442 \u0437\u0430\u0434\u0430\u0451\u0442 <code>severity<\/code>, \u0430 severity \u0434\u0430\u0451\u0442 \u0448\u0442\u0440\u0430\u0444 \u043a \u0431\u0430\u043b\u043b\u0443: \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442 \u0434\u043e\u0435\u0437\u0436\u0430\u0435\u0442 \u0434\u043e \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0439 \u0446\u0438\u0444\u0440\u044b.<\/p>\n<p>\u0414\u0432\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430, \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u0434\u0432\u043e\u0439\u043d\u043e\u0439 \u0441\u0447\u0451\u0442 \u043f\u0435\u0440\u0435\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u0435\u0440\u0434\u0438\u043a\u0442:<\/p>\n<pre><code class=\"python\">from bs4 import BeautifulSoupfrom geo_optimizer.core.audit_negative import audit_negative_signalsfrom geo_optimizer.models.results import ContentResult, MetaResult, SchemaResultMENU = \"\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0420\u0430\u0437\u0434\u0435\u043b\u044b \u0410\u0440\u0445\u0438\u0432 \u0422\u0435\u0433\u0438\"mini = (\"&lt;html&gt;&lt;body&gt;&lt;header&gt;&lt;nav&gt;\" + MENU + \"&lt;\/nav&gt;&lt;\/header&gt;&lt;p&gt;\u0422\u0435\u043a\u0441\u0442.&lt;\/p&gt;\"        \"&lt;footer&gt;&lt;nav&gt;\" + MENU + \"&lt;\/nav&gt;&lt;\/footer&gt;&lt;\/body&gt;&lt;\/html&gt;\")page = mini.replace(\"&lt;p&gt;\u0422\u0435\u043a\u0441\u0442.&lt;\/p&gt;\", \"&lt;p&gt;\u041a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 \u0430\u0431\u0437\u0430\u0446 \u043f\u0440\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0444\u043e\u0440\u043c\u0443\u043b\u044b.&lt;\/p&gt;\")def fallback_fixed(s):    total = len(s.get_text(\" \", True))    tops = [t for t in s.find_all([\"nav\", \"footer\", \"header\"])            if t.find_parent([\"nav\", \"footer\", \"header\"]) is None]    boiler = sum(len(t.get_text(\" \", True)) for t in tops)    return round(min(boiler \/ total, 1.0), 2) if total else 0.0for name, html in ((\"\u043c\u0438\u043d\u0438\", mini), (\"\u0432\u0442\u043e\u0440\u043e\u0439\", page)):    s = BeautifulSoup(html, \"html.parser\")    r = audit_negative_signals(s, html, ContentResult(), MetaResult(), SchemaResult(),                               soup_clean=s).boilerplate_ratio    f = fallback_fixed(s)    print(f\"{name}: \u043f\u0430\u043a\u0435\u0442 ratio {r}, \u0444\u043b\u0430\u0433 {r &gt; 0.6} | \u043f\u0440\u0430\u0432\u043a\u0430 ratio {f}, \u0444\u043b\u0430\u0433 {f &gt; 0.6} |\"          f\" \u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442 {len(s.get_text(' ', True))} \u0437\u043d\u0430\u043a\u043e\u0432\")<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<pre><code>\u043c\u0438\u043d\u0438: \u043f\u0430\u043a\u0435\u0442 ratio 1.73, \u0444\u043b\u0430\u0433 True | \u043f\u0440\u0430\u0432\u043a\u0430 ratio 0.87, \u0444\u043b\u0430\u0433 True | \u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442 60 \u0437\u043d\u0430\u043a\u043e\u0432\u0432\u0442\u043e\u0440\u043e\u0439: \u043f\u0430\u043a\u0435\u0442 ratio 1.13, \u0444\u043b\u0430\u0433 True | \u043f\u0440\u0430\u0432\u043a\u0430 ratio 0.57, \u0444\u043b\u0430\u0433 False | \u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442 92 \u0437\u043d\u0430\u043a\u043e\u0432<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u043c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435 \u043c\u0435\u043d\u044e 26 \u0437\u043d\u0430\u043a\u043e\u0432, \u0443\u0437\u043b\u043e\u0432 \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u0447\u0435\u0442\u044b\u0440\u0435 (<code>header<\/code>, <code>nav<\/code>, <code>footer<\/code>, <code>nav<\/code>), 26 * 4 = 104 \u043f\u0440\u0438 60 \u0437\u043d\u0430\u043a\u0430\u0445 \u0442\u0435\u043a\u0441\u0442\u0430, \u043e\u0442\u0441\u044e\u0434\u0430 1.73. \u0412\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u043e\u0434\u043d\u0430 \u0438 \u0442\u0430 \u0436\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043f\u043e \u043a\u043e\u0434\u0443 \u043f\u0430\u043a\u0435\u0442\u0430 \u00ab\u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u043c\u00bb, \u0430 \u043f\u0440\u0438 \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u0435 \u0431\u0435\u0437 \u0434\u0432\u043e\u0439\u043d\u043e\u0433\u043e \u0441\u0447\u0451\u0442\u0430 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043d\u0438\u0436\u0435 \u043f\u043e\u0440\u043e\u0433\u0430.<\/p>\n<p>\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432 \u043f\u0430\u043a\u0435\u0442\u0435 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c: <code>detect_boilerplate_ratio<\/code> \u0432 <code>core\/citability.py<\/code> \u0443\u0431\u0438\u0440\u0430\u0435\u0442 <code>nav<\/code>, <code>header<\/code> \u0438 <code>footer<\/code> \u0447\u0435\u0440\u0435\u0437 <code>decompose<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0432\u043e\u0439\u043d\u043e\u0433\u043e \u0441\u0447\u0451\u0442\u0430 \u0442\u0430\u043c \u043d\u0435\u0442, \u0430 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0435\u0439 \u043f\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044e. \u041d\u0430 \u0442\u0435\u0445 \u0436\u0435 \u0434\u0432\u0443\u0445 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0445 \u043e\u043d\u0430 \u043f\u0435\u0447\u0430\u0442\u0430\u0435\u0442 \u0434\u043e\u043b\u044e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 0.1 \u0438 0.41, \u0442\u043e \u0435\u0441\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d 0.9 \u0438 0.59, \u0438 \u0432\u0442\u043e\u0440\u043e\u0435 \u0441\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0441 <code>fallback_fixed<\/code>. \u041e\u0431\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0433\u043e\u043d\u0435 <code>geo audit<\/code>: <code>core\/audit.py<\/code> \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 <code>audit_citability<\/code> \u0440\u044f\u0434\u043e\u043c \u0441 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430\u043c\u0438. \u041d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 python.org \u043f\u0435\u0440\u0432\u0430\u044f \u043f\u0435\u0447\u0430\u0442\u0430\u0435\u0442 \u0434\u043e\u043b\u044e \u0448\u0430\u0431\u043b\u043e\u043d\u0430 0.65, \u0442\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 35 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043e\u0432, \u0432\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u043b\u044e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 0.03 (\u043e\u043d\u0430 \u043d\u0435 \u0441\u043c\u043e\u0442\u0440\u0438\u0442 <code>role=\"main\"<\/code> \u0438 \u0443\u0445\u043e\u0434\u0438\u0442 \u0432 \u044d\u0432\u0440\u0438\u0441\u0442\u0438\u043a\u0443). \u041d\u0430 \u043b\u0438\u0441\u0442\u0438\u043d\u0433\u0435 \u0441\u0442\u0430\u0442\u0435\u0439 \u0425\u0430\u0431\u0440\u0430 \u043e\u0431\u0435 \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u044b: 0.02 \u0438 0.98.<\/p>\n<p>\u0423 \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a-\u0432\u0435\u0442\u043a\u0438 \u0441\u0432\u043e\u044f \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c: \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u043c \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u0441\u0451 \u0432\u043d\u0435 \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a\u0430, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0445 \u0441\u0435\u043a\u0446\u0438\u0439.<\/p>\n<pre><code class=\"python\"># \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430from geo_optimizer.utils.http import fetch_urlfor url in (\"https:\/\/www.python.org\/\", \"https:\/\/habr.com\/ru\/articles\/\"):    raw = fetch_url(url)[0].text or \"\"    soup = BeautifulSoup(raw, \"html.parser\")    for t in soup([\"script\", \"style\", \"noscript\", \"template\"]):        t.decompose()    lm = soup.find(\"main\") or soup.find(\"article\") or soup.find(attrs={\"role\": \"main\"})    r = audit_negative_signals(soup, raw, ContentResult(), MetaResult(), SchemaResult(),                               soup_clean=soup).boilerplate_ratio    print(url, \"| \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a:\", lm.name if lm else None, \"| ratio:\", r)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<pre><code>https:\/\/www.python.org\/ | \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a: section | ratio: 0.65https:\/\/habr.com\/ru\/articles\/ | \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a: main | ratio: 0.02<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u041d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 python.org \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a \u044d\u0442\u043e <code>section role=\"main\"<\/code> \u043b\u0438\u0448\u044c \u0441 \u0447\u0430\u0441\u0442\u044c\u044e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430, \u043d\u0430 \u043b\u0438\u0441\u0442\u0438\u043d\u0433\u0435 \u0425\u0430\u0431\u0440\u0430 \u0432 <code>main<\/code> \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430. \u0420\u0430\u0437\u043d\u0438\u0446\u0430 \u0432 \u0442\u0440\u0438\u0434\u0446\u0430\u0442\u044c \u0440\u0430\u0437 \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438 \u0441\u043e \u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u0430\u0440\u043a\u0430\u0441\u043e\u043c (\u0448\u0430\u043f\u043a\u0430, \u043f\u043e\u0434\u0432\u0430\u043b, \u043f\u043e\u0442\u043e\u043a \u0431\u043b\u043e\u043a\u043e\u0432) \u0437\u0430\u0434\u0430\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u043c, \u0447\u0442\u043e \u0442\u0435\u043c\u0430 \u043f\u043e\u043b\u043e\u0436\u0438\u043b\u0430 \u0432 \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a.<\/p>\n<p>\u041b\u0435\u0447\u0438\u0442\u0441\u044f \u0442\u0430\u043a: \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>detect_boilerplate_ratio<\/code> \u0432\u043c\u0435\u0441\u0442\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0432\u0435\u0442\u043a\u0438 \u0432 <code>audit_negative.py<\/code>. \u0415\u0441\u043b\u0438 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0434\u0432\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0442\u043e \u0432 \u0437\u0430\u043f\u0430\u0441\u043d\u043e\u0439 \u0432\u0435\u0442\u043a\u0435 \u0431\u0440\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0440\u0445\u043d\u0435\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 \u0443\u0437\u043b\u044b (\u043a\u0430\u043a \u0432 <code>fallback_fixed<\/code>) \u043b\u0438\u0431\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0443\u0437\u043b\u043e\u0432 \u043f\u0435\u0440\u0435\u0434 \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u043e\u043c \u0434\u043b\u0438\u043d\u044b, \u043f\u043b\u044e\u0441 <code>min(..., 1.0)<\/code>, \u0447\u0442\u043e\u0431\u044b \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c ratio \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u0430\u0441\u044c \u0434\u043e\u043b\u0435\u0439.<\/p>\n<h3>\u041d\u0430\u0445\u043e\u0434\u043a\u0430 2: \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0437\u043d\u0430\u044e\u0442 \u043a\u0438\u0440\u0438\u043b\u043b\u0438\u0446\u044b<\/h3>\n<p><code>core\/audit_rag.py<\/code>, \u0446\u0438\u0442\u0430\u0442\u0430 \u043a\u0430\u043a \u0432 \u043f\u0430\u043a\u0435\u0442\u0435:<\/p>\n<pre><code class=\"python\">_DEFINITION_RE = re.compile(    r\"^[A-Z][^.]{5,60}\\b(?:is|are|refers?\\s+to|means?|describes?|represents?)\\b\",    re.MULTILINE,)_ANCHOR_RE = re.compile(r\"(?&lt;=[.!?]\\s)[A-Z][^.!?]{30,200}[.!?]\")<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043b\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c \u0432\u0438\u0434\u0430 \u00abX is Y\u00bb. \u0412\u0442\u043e\u0440\u0430\u044f \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u00ab\u044f\u043a\u043e\u0440\u043d\u044b\u0435\u00bb \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u0441\u0430\u043c\u043e\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u0435 \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f 30-200 \u0437\u043d\u0430\u043a\u043e\u0432 (\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u043d\u0430\u0434 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u043e\u0439 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u0431\u0435\u0449\u0430\u0435\u0442 \u00ab10-40 words\u00bb, \u0442\u043e \u0435\u0441\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u0448\u0430\u0431\u043b\u043e\u043d \u043c\u0435\u0440\u044f\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0435\u0434\u0438\u043d\u0438\u0446\u044b). \u041e\u0431\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0438\u0434\u0443\u0442 \u0432 <code>chunk_readiness_score<\/code>. \u041a\u043b\u0430\u0441\u0441 <code>[A-Z]<\/code> \u043a\u0438\u0440\u0438\u043b\u043b\u0438\u0446\u0443 \u043d\u0435 \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u0442, \u0430 \u0441\u0432\u044f\u0437\u043a\u0438 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438\u0435: \u00abX \u044d\u0442\u043e Y\u00bb, \u00ab\u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f\u00bb, \u00ab\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439\u00bb \u0432 \u0448\u0430\u0431\u043b\u043e\u043d \u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0442. \u0411\u0435\u0440\u0451\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043f\u0440\u044f\u043c\u043e \u0438\u0437 \u043f\u0430\u043a\u0435\u0442\u0430 \u0438 \u043e\u0434\u0438\u043d \u0442\u0435\u043a\u0441\u0442 \u0432 \u0434\u0432\u0443\u0445 \u044f\u0437\u044b\u043a\u0430\u0445:<\/p>\n<pre><code class=\"python\">import refrom geo_optimizer.core.audit_rag import _ANCHOR_RE, _DEFINITION_REUP = \"A-Z\u0410-\u042f\u0401\"DEF_FIX = re.compile(    rf\"^[{UP}][^.]{{5,60}}(?:\\b(?:is|are|refers?\\s+to|means?|describes?|represents?)\\b\"    r\"|\\s(?:\u044d\u0442\u043e|\u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f|\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\\s+\u0441\u043e\u0431\u043e\u0439|\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442)\\b)\", re.MULTILINE)ANCHOR_FIX = re.compile(rf\"(?&lt;=[.!?]\\s)[{UP}][^.!?]{{30,200}}[.!?]\")ru = (\"\u0413\u0435\u043d\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u043f\u0440\u0438\u0451\u043c\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u043e\u0442\u0432\u0435\u0442 \u043c\u043e\u0434\u0435\u043b\u0438. \"      \"\u041c\u043e\u0434\u0435\u043b\u044c \u0437\u0430\u0431\u0438\u0440\u0430\u0435\u0442 \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c.\")en = (\"Generative optimization is a set of techniques for landing in a model answer. \"      \"The model lifts a ready fragment of text from the page along with its source.\")for name, text in ((\"ru\", ru), (\"en\", en)):    print(f\"{name}: \u043f\u0430\u043a\u0435\u0442 definition={bool(_DEFINITION_RE.search(text[:150]))} \"          f\"anchors={len(_ANCHOR_RE.findall(text))} | \u043f\u0440\u0430\u0432\u043a\u0430 \"          f\"definition={bool(DEF_FIX.search(text[:150]))} \"          f\"anchors={len(ANCHOR_FIX.findall(text))}\")<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<pre><code>ru: \u043f\u0430\u043a\u0435\u0442 definition=False anchors=0 | \u043f\u0440\u0430\u0432\u043a\u0430 definition=True anchors=1en: \u043f\u0430\u043a\u0435\u0442 definition=True anchors=1 | \u043f\u0440\u0430\u0432\u043a\u0430 definition=True anchors=1<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u041e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043f\u043e \u0441\u043c\u044b\u0441\u043b\u0443 \u0442\u0435\u043a\u0441\u0442: \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0438 \u043e\u0434\u0438\u043d \u044f\u043a\u043e\u0440\u044c, \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c \u043d\u043e\u043b\u044c \u044f\u043a\u043e\u0440\u0435\u0439 \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u0442. \u0412 <code>_compute_score<\/code> \u0438\u0437 \u0442\u043e\u0433\u043e \u0436\u0435 \u0444\u0430\u0439\u043b\u0430 \u044d\u0442\u043e 10 \u0431\u0430\u043b\u043b\u043e\u0432 \u0437\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0438 \u0434\u043e 10 \u0437\u0430 \u044f\u043a\u043e\u0440\u044f: \u0434\u043e \u043f\u044f\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 <code>chunk_readiness_score<\/code> \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0440\u0443\u0441\u0441\u043a\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0435\u0451 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430.<\/p>\n<p>\u041f\u043e\u0447\u0438\u043d\u043a\u0430: \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u0438\u0440\u0438\u043b\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438 \u0440\u0443\u0441\u0441\u043a\u0438\u0435 \u0441\u0432\u044f\u0437\u043a\u0438, \u043a\u0430\u043a \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u043b\u0438\u0431\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u044f\u0437\u044b\u043a \u0432 \u043a\u043e\u043d\u0444\u0438\u0433 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (<code>.geo-optimizer.yml<\/code> \u043f\u0430\u043a\u0435\u0442 \u0443\u0436\u0435 \u0447\u0438\u0442\u0430\u0435\u0442). \u0418 \u043f\u043e\u0431\u043e\u0447\u043d\u044b\u0439 \u044d\u0444\u0444\u0435\u043a\u0442 <code>(?&lt;=[.!?]\\s)<\/code>: \u043f\u0435\u0440\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u044f\u043a\u043e\u0440\u0435\u043c \u043d\u0435 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043d\u0438\u043a\u043e\u0433\u0434\u0430, \u043e\u0442\u0441\u044e\u0434\u0430 \u043e\u0434\u0438\u043d \u044f\u043a\u043e\u0440\u044c \u043d\u0430 \u0434\u0432\u0430 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<h3>\u041d\u0430\u0445\u043e\u0434\u043a\u0430 3: \u0441\u0442\u043e \u0431\u0430\u043b\u043b\u043e\u0432 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0435 \u0438\u0437 \u0432\u0441\u0435\u0433\u043e, \u0447\u0442\u043e \u043f\u0435\u0447\u0430\u0442\u0430\u0435\u0442\u0441\u044f<\/h3>\n<p><code>models\/config.py<\/code>:<\/p>\n<pre><code class=\"python\">CATEGORY_MAX = {    \"robots\": 18, \"llms\": 18, \"schema\": 16, \"meta\": 14,    \"content\": 12, \"brand_entity\": 10, \"signals\": 6, \"ai_discovery\": 6,}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0421\u0443\u043c\u043c\u0430 \u0440\u043e\u0432\u043d\u043e 100. \u041d\u043e \u0432 \u0440\u0430\u0437\u0431\u0438\u0432\u043a\u0435 \u0438\u0437 <code>core\/scoring.py<\/code> \u0435\u0441\u0442\u044c \u043a\u043b\u044e\u0447, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0435 \u043d\u0435\u0442:<\/p>\n<pre><code class=\"python\">from geo_optimizer.models.config import CATEGORY_MAXfrom geo_optimizer.core.scoring import compute_score_breakdownfrom geo_optimizer.models.results import (ContentResult, LlmsTxtResult, MetaResult,                                          RobotsResult, SchemaResult)keys = list(compute_score_breakdown(RobotsResult(), LlmsTxtResult(), SchemaResult(),                                    MetaResult(), ContentResult()))print(\"\u0441\u0443\u043c\u043c\u0430 CATEGORY_MAX:\", sum(CATEGORY_MAX.values()),      \"| \u043d\u0435\u0442 \u0432 CATEGORY_MAX:\", [k for k in keys if k not in CATEGORY_MAX])print(\"rag_chunk \u0438 context_window \u0432 \u0431\u0430\u043b\u043b\u0435:\", \"rag_chunk\" in keys, \"context_window\" in keys)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<pre><code>\u0441\u0443\u043c\u043c\u0430 CATEGORY_MAX: 100 | \u043d\u0435\u0442 \u0432 CATEGORY_MAX: ['negative_penalty']rag_chunk \u0438 context_window \u0432 \u0431\u0430\u043b\u043b\u0435: False False<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p><code>negative_penalty<\/code> \u043e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u0435\u043d (\u043e\u0442 -1 \u0434\u043e -5 \u043f\u043e <code>NEGATIVE_PENALTY_LOW\/MED\/HIGH<\/code>), \u0432 \u0441\u043e\u0442\u043d\u044e \u043d\u0435 \u0432\u0445\u043e\u0434\u0438\u0442 \u0438 \u0432\u044b\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435, \u0430 \u0438\u0442\u043e\u0433 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a <code>max(0, min(total, 100))<\/code>. \u0417\u043d\u0430\u0447\u0438\u0442, 100 \u043d\u0435\u0434\u043e\u0441\u0442\u0438\u0436\u0438\u043c\u044b, \u0435\u0441\u043b\u0438 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0445\u043e\u0442\u044c \u043e\u0434\u0438\u043d \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b. <code>geo audit --url https:\/\/www.python.org\/ --format json<\/code> \u0434\u0430\u043b 42 \u043f\u0440\u0438 \u0440\u0430\u0437\u0431\u0438\u0432\u043a\u0435 <code>robots 15, llms 0, schema 3, meta 11, content 10, signals 5, ai_discovery 0, brand_entity 3, negative_penalty -5<\/code>: 47 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u0438\u043d\u0443\u0441 5.<\/p>\n<p>\u0412\u0442\u043e\u0440\u043e\u0435 \u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0435 \u0432\u0430\u0436\u043d\u0435\u0435: <code>rag_chunk<\/code> \u0438 <code>context_window<\/code> \u0441\u0447\u0438\u0442\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0440\u043e\u0433\u043e\u043d\u0435 \u0438 \u043f\u0435\u0447\u0430\u0442\u0430\u044e\u0442\u0441\u044f \u0441\u0432\u043e\u0438\u043c\u0438 \u0448\u043a\u0430\u043b\u0430\u043c\u0438 0-100, \u043d\u043e \u0432 \u0431\u0430\u043b\u043b \u043d\u0435 \u0432\u0445\u043e\u0434\u044f\u0442. \u0423 \u0442\u043e\u0439 \u0436\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0431\u0430\u043b\u043b 42 \u043f\u0440\u0438 <code>chunk_readiness_score<\/code> 47 (\u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u0441 \u0441\u0443\u043c\u043c\u043e\u0439 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0435, \u044d\u0442\u043e \u0440\u0430\u0437\u043d\u044b\u0435 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u044b). \u0412\u044b\u0441\u043e\u043a\u0438\u0439 \u0431\u0430\u043b\u043b \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0441 \u043d\u0435\u0433\u043e\u0434\u043d\u043e\u0439 \u0434\u043b\u044f \u043d\u0430\u0440\u0435\u0437\u043a\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 \u0442\u0435\u043a\u0441\u0442\u0430.<\/p>\n<p>\u041f\u043e\u0447\u0438\u043d\u043a\u0430: \u0441\u043e\u0431\u0440\u0430\u0442\u044c <code>CATEGORY_MAX<\/code> \u0438 \u0448\u0442\u0440\u0430\u0444 \u0432 \u043e\u0434\u043d\u0443 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441 \u0442\u0435\u0441\u0442\u043e\u043c \u043d\u0430 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0430 \u0432 \u0432\u044b\u0432\u043e\u0434\u0435 \u043e\u0442\u0434\u0435\u043b\u0438\u0442\u044c \u00ab\u0431\u0430\u043b\u043b\u00bb \u043e\u0442 \u00ab\u043c\u0435\u0442\u0440\u0438\u043a \u0432\u043d\u0435 \u0431\u0430\u043b\u043b\u0430\u00bb, \u0447\u0442\u043e\u0431\u044b <code>chunk_readiness_score<\/code> \u0440\u044f\u0434\u043e\u043c \u0441 \u0438\u0442\u043e\u0433\u043e\u043c \u043d\u0435 \u0447\u0438\u0442\u0430\u043b\u0441\u044f \u043a\u0430\u043a \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u044c.<\/p>\n<h3>\u041d\u0430\u0445\u043e\u0434\u043a\u0430 4: \u0434\u0435\u0441\u044f\u0442\u044c \u0441\u0435\u043a\u0443\u043d\u0434 \u043d\u0430 \u043f\u044f\u0442\u043d\u0430\u0434\u0446\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/h3>\n<p><code>core\/batch_audit.py<\/code>, \u0446\u0438\u0442\u0430\u0442\u0430 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0430:<\/p>\n<pre><code class=\"python\">try:    return await asyncio.wait_for(        _audit_single_url(url, use_cache=use_cache, project_config=project_config),        timeout=AUDIT_TIMEOUT_SECONDS,    )except asyncio.TimeoutError:    result = AuditResult(url=url, error=f\"Timeout ({AUDIT_TIMEOUT_SECONDS}s)\", band=\"critical\")<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p><code>AUDIT_TIMEOUT_SECONDS = 10<\/code> \u043e\u0442\u0432\u0435\u0434\u0435\u043d\u044b \u043d\u0435 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441, \u0430 \u043d\u0430 \u0432\u0435\u0441\u044c \u0430\u0443\u0434\u0438\u0442 \u043e\u0434\u043d\u043e\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430, \u043f\u043e\u0434 \u0441\u0435\u043c\u0430\u0444\u043e\u0440\u043e\u043c \u043d\u0430 <code>concurrency<\/code>. \u0412\u043d\u0443\u0442\u0440\u0438 \u0430\u0434\u0440\u0435\u0441\u0430 \u043f\u0430\u043a\u0435\u0442 \u043e\u0434\u043d\u043e\u0439 \u043f\u0430\u0447\u043a\u043e\u0439 \u0442\u044f\u043d\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, <code>robots.txt<\/code>, <code>llms.txt<\/code>, <code>llms-full.txt<\/code> \u0438 \u0447\u0435\u0442\u044b\u0440\u0435 \u0442\u043e\u0447\u043a\u0438 AI-\u0434\u0438\u0441\u043a\u0430\u0432\u0435\u0440\u0438 (<code>\/.well-known\/ai.txt<\/code>, <code>\/ai\/{summary,faq,service}.json<\/code>), \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0443 \u0431\u043e\u0442\u043e\u0432 \u043d\u0430 CDN: \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0440\u043e\u0441 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u044b\u043c User-Agent \u0438 \u0448\u0435\u0441\u0442\u044c \u0431\u043e\u0442\u043e\u0432\u0441\u043a\u0438\u043c\u0438. \u0422\u0430\u0439\u043c\u0430\u0443\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0442\u043e\u0436\u0435 10 \u0441\u0435\u043a\u0443\u043d\u0434: <code>timeout: int = 10<\/code> \u0432 <code>utils\/http_async.py<\/code> \u043d\u0430 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u043c \u043f\u0443\u0442\u0438 \u0438 \u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0436\u0435 \u0432 <code>utils\/http.py<\/code> \u043d\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u043c. \u041e\u0434\u0438\u043d \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u044a\u0435\u0434\u0430\u0435\u0442 \u0432\u0435\u0441\u044c \u0431\u044e\u0434\u0436\u0435\u0442 \u0430\u0434\u0440\u0435\u0441\u0430.<\/p>\n<p>\u041f\u043e\u0434\u043d\u0438\u043c\u0435\u043c \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0443 \u0438 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u044b. \u0412 CLI \u044d\u0442\u043e <code>geo audit --sitemap &lt;url&gt; --concurrency 5 --max-urls 5<\/code>, \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b <code>batch<\/code> \u043d\u0435\u0442. \u0410\u043d\u0442\u0438-SSRF \u043d\u0435 \u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043d\u0430 127.0.0.1, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u043e\u0434\u043c\u0435\u043d\u0435\u043d\u0430, \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0434\u0438 \u044d\u0442\u043e\u0433\u043e. \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a <code>demo.py<\/code>, \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u044d\u0442\u043e \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445:<\/p>\n<pre><code class=\"python\">import collections, sys, threading, timefrom http.server import BaseHTTPRequestHandler, ThreadingHTTPServerimport geo_optimizer.utils.validators as VV.resolve_and_validate_url = lambda u: (True, None, [\"127.0.0.1\"])  # \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0434\u0438 127.0.0.1from geo_optimizer.core.batch_audit import run_batch_auditDELAY, hits = float(sys.argv[1]), collections.Counter()PAGES = [f\"\/p{i}\" for i in range(1, 6)]PAGE = b\"&lt;html&gt;&lt;head&gt;&lt;title&gt;T&lt;\/title&gt;&lt;\/head&gt;&lt;body&gt;&lt;h1&gt;H&lt;\/h1&gt;&lt;p&gt;text&lt;\/p&gt;&lt;\/body&gt;&lt;\/html&gt;\"class H(BaseHTTPRequestHandler):    def do_GET(self):        hits[self.path] += 1; time.sleep(DELAY)        body = MAP if \"sitemap\" in self.path else PAGE if self.path in PAGES else b\"\"        self.send_response(200 if body else 404); self.send_header(\"Content-Length\", str(len(body)))        self.end_headers(); self.wfile.write(body)    def log_message(self, *a): passsrv = ThreadingHTTPServer((\"127.0.0.1\", 0), H)   # 0 = \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u044b\u0439 \u043f\u043e\u0440\u0442BASE = f\"http:\/\/127.0.0.1:{srv.server_address[1]}\"MAP = (\"&lt;urlset&gt;\" + \"\".join(f\"&lt;url&gt;&lt;loc&gt;{BASE}{p}&lt;\/loc&gt;&lt;\/url&gt;\" for p in PAGES) + \"&lt;\/urlset&gt;\").encode()threading.Thread(target=srv.serve_forever, daemon=True).start()t0 = time.perf_counter()res = run_batch_audit(f\"{BASE}\/sitemap.xml\", max_urls=5, concurrency=5)print(f\"\u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 {DELAY}s, \u0431\u0430\u0442\u0447 {time.perf_counter()-t0:.1f}s, \u0431\u0430\u043b\u043b\u044b {[p.score for p in res.pages]}\")print(\"\u043e\u0448\u0438\u0431\u043a\u0438:\", dict(collections.Counter(p.error or \"\u043d\u0435\u0442\" for p in res.pages)),      \"| \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432\u0441\u0435\u0433\u043e:\", sum(hits.values()), \"| \u043a \/p1:\", hits[\"\/p1\"])print(\"\u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0445:\", res.successful_urls, \"| \u0443\u043f\u0430\u0432\u0448\u0438\u0445:\", res.failed_urls,      \"| \u0441\u0440\u0435\u0434\u043d\u0438\u0439 \u0431\u0430\u043b\u043b:\", res.average_score)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<pre><code>$ $PY demo.py 0\u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 0.0s, \u0431\u0430\u0442\u0447 0.2s, \u0431\u0430\u043b\u043b\u044b [6, 6, 6, 6, 6]\u043e\u0448\u0438\u0431\u043a\u0438: {'\u043d\u0435\u0442': 5} | \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432\u0441\u0435\u0433\u043e: 76 | \u043a \/p1: 8\u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0445: 5 | \u0443\u043f\u0430\u0432\u0448\u0438\u0445: 0 | \u0441\u0440\u0435\u0434\u043d\u0438\u0439 \u0431\u0430\u043b\u043b: 6.0$ $PY demo.py 1.5\u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 1.5s, \u0431\u0430\u0442\u0447 13.7s, \u0431\u0430\u043b\u043b\u044b [0, 0, 0, 0, 0]\u043e\u0448\u0438\u0431\u043a\u0438: {'Timeout (10s)': 5} | \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432\u0441\u0435\u0433\u043e: 76 | \u043a \/p1: 8\u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0445: 0 | \u0443\u043f\u0430\u0432\u0448\u0438\u0445: 5 | \u0441\u0440\u0435\u0434\u043d\u0438\u0439 \u0431\u0430\u043b\u043b: 0.0<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>76 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u043f\u044f\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u043e\u0432: \u043e\u0434\u0438\u043d \u043d\u0430 \u043a\u0430\u0440\u0442\u0443 \u0441\u0430\u0439\u0442\u0430 \u0438 \u043f\u043e 15 \u043d\u0430 \u0430\u0434\u0440\u0435\u0441, \u0438\u0437 \u043d\u0438\u0445 8 \u043a \u0441\u0430\u043c\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 (\u043e\u0434\u0438\u043d \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0438 \u0441\u0435\u043c\u044c \u0441 \u043f\u043e\u0434\u043c\u0435\u043d\u043e\u0439 User-Agent) \u0438 7 \u043a \u0441\u043e\u043f\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u0444\u0430\u0439\u043b\u0430\u043c. \u0422\u0430\u043a \u0447\u0442\u043e <code>--concurrency 5<\/code> (\u044d\u0442\u043e \u0434\u0435\u0444\u043e\u043b\u0442) \u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u043f\u043e\u043b\u0451\u0442\u0435 \u043f\u044f\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u043f\u043e \u043f\u044f\u0442\u043d\u0430\u0434\u0446\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a\u0430\u0436\u0434\u044b\u0439: \u0432\u043e\u0441\u0435\u043c\u044c \u0443\u0445\u043e\u0434\u044f\u0442 \u043e\u0434\u043d\u0438\u043c <code>gather<\/code>, \u0441\u0435\u043c\u044c \u0441\u043b\u0435\u0434\u043e\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e. \u0417\u0430\u0433\u043b\u0443\u0448\u043a\u0430 \u0441\u043e \u0441\u0447\u0451\u0442\u0447\u0438\u043a\u043e\u043c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0434\u0430\u0451\u0442 \u043f\u0438\u043a 40, \u0430 \u043d\u0435 75. \u0421\u0435\u0440\u0432\u0435\u0440 \u0441 \u043e\u0442\u0432\u0435\u0442\u043e\u043c \u0437\u0430 1.5 \u0441\u0435\u043a\u0443\u043d\u0434\u044b \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u0435\u0441\u044c \u0431\u0430\u0442\u0447 \u0432 \u043d\u0443\u043b\u0438.<\/p>\n<p>\u0421\u0440\u0435\u0434\u043d\u0435\u0435 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0430\u0432\u0442\u043e\u0440 \u0437\u0430\u0449\u0438\u0442\u0438\u043b: <code>_aggregate_batch_result<\/code> \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0435\u0433\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c \u0431\u0435\u0437 \u043e\u0448\u0438\u0431\u043a\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043e\u0442\u0447\u0451\u0442\u0435 \u0432\u0438\u0434\u043d\u043e <code>\u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0445: 0<\/code> \u0438 <code>\u0443\u043f\u0430\u0432\u0448\u0438\u0445: 5<\/code>, \u0430 \u043d\u043e\u043b\u044c \u0432 <code>average_score<\/code> \u044d\u0442\u043e \u0434\u0435\u0444\u043e\u043b\u0442 \u043f\u043e\u043b\u044f \u043f\u0440\u0438 \u043f\u0443\u0441\u0442\u043e\u0439 \u0432\u044b\u0431\u043e\u0440\u043a\u0435. \u041d\u043e \u0440\u044f\u0434\u043e\u043c \u0441\u0442\u043e\u0438\u0442 <code>average_band: critical<\/code>, \u0438 \u0432 \u0442\u0430\u043a\u043e\u0439 \u043f\u0430\u0440\u0435 \u043d\u043e\u043b\u044c \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043e\u0446\u0435\u043d\u043a\u0430 \u0441\u0430\u0439\u0442\u0430, \u0445\u043e\u0442\u044f \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u043e\u0442\u0437\u044b\u0432\u0447\u0438\u0432\u043e\u0441\u0442\u044c.<\/p>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 76, \u0445\u043e\u0442\u044f \u0432\u0441\u0435 \u043f\u044f\u0442\u044c \u0430\u0443\u0434\u0438\u0442\u043e\u0432 \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u044b. \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 CDN \u0438\u0434\u0451\u0442 \u0447\u0435\u0440\u0435\u0437 <code>asyncio.to_thread<\/code>, \u0430 \u043f\u043e\u0442\u043e\u043a <code>wait_for<\/code> \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0435 \u043c\u043e\u0436\u0435\u0442: \u043e\u043d \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442 \u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0431\u0440\u043e\u0448\u0435\u043d, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0430\u0442\u0447 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u043a\u043e\u043b\u043e \u0447\u0435\u0442\u044b\u0440\u043d\u0430\u0434\u0446\u0430\u0442\u043e\u0439 \u0441\u0435\u043a\u0443\u043d\u0434\u044b \u0432\u043c\u0435\u0441\u0442\u043e 11.5 (\u0443 \u043c\u0435\u043d\u044f 13.7-13.9 \u043f\u043e \u043f\u0440\u043e\u0433\u043e\u043d\u0430\u043c). \u041d\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u043c \u043f\u0443\u0442\u0438 (\u0444\u043b\u0430\u0433 <code>--cache<\/code> \u0438\u043b\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 <code>httpx<\/code>) \u0432 \u043f\u043e\u0442\u043e\u043a \u0443\u0445\u043e\u0434\u0438\u0442 \u0432\u0435\u0441\u044c \u0430\u0443\u0434\u0438\u0442, \u0430 \u043d\u0435 \u043e\u0434\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 CDN, \u0442\u0430\u043a \u0447\u0442\u043e \u0442\u0430\u043c \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u043d\u0435 \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u0442 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0438\u0447\u0435\u0433\u043e.<\/p>\n<p>\u041f\u043e\u0447\u0438\u043d\u043a\u0430: \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0431\u044e\u0434\u0436\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441, \u0430 \u043d\u0435 \u043d\u0430 \u0430\u0434\u0440\u0435\u0441, \u043b\u0438\u0431\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 <code>AUDIT_TIMEOUT_SECONDS<\/code> \u0432 \u043e\u043f\u0446\u0438\u044e CLI \u0438 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433. \u0418 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0444\u043b\u0430\u0433 \u043e\u0442\u043c\u0435\u043d\u044b, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043c\u0435\u043d\u0451\u043d\u043d\u044b\u0439 \u0430\u0443\u0434\u0438\u0442 \u043d\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0442\u0440\u0430\u0444\u0438\u043a.<\/p>\n<h3>\u041d\u0430\u0445\u043e\u0434\u043a\u0430 5: \u043f\u043e\u0440\u043e\u0433 \u0432\u0435\u0441\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432 \u0441\u044b\u0440\u044b\u0445 \u0431\u0430\u0439\u0442\u0430\u0445 HTML<\/h3>\n<p><code>core\/agent_access.py<\/code>, \u043a\u043e\u043c\u0430\u043d\u0434\u0430 <code>geo access<\/code> (\u0432 \u0431\u0430\u043b\u043b <code>geo audit<\/code> \u044d\u0442\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0435 \u0432\u0445\u043e\u0434\u0438\u0442), \u0446\u0438\u0442\u0430\u0442\u0430 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0430:<\/p>\n<pre><code class=\"python\">result.page_weight_bytes = len(raw_html.encode(\"utf-8\"))if result.page_weight_bytes &gt; 200_000:    result.warnings.append(f\"Heavy initial HTML: ... (target: under 200KB ...)\")<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0440\u043e\u0433 \u0437\u0430\u0448\u0438\u0442 \u0447\u0438\u0441\u043b\u043e\u043c \u0438 \u043d\u0435 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f. \u0427\u0442\u043e \u043e\u043d \u043b\u043e\u0432\u0438\u0442:<\/p>\n<pre><code class=\"python\">from bs4 import BeautifulSoupfrom geo_optimizer.utils.http import fetch_urlfor url in (\"https:\/\/www.python.org\/\", \"https:\/\/habr.com\/ru\/articles\/\"):    raw = fetch_url(url)[0].text or \"\"    soup = BeautifulSoup(raw, \"html.parser\")    for t in soup([\"script\", \"style\", \"noscript\", \"template\"]):        t.decompose()    html, text = len(raw.encode()), len(soup.get_text(\" \", True).encode())    print(url, f\"HTML {html\/1000:.0f} KB,\", \"\u0448\u0442\u0440\u0430\u0444\" if html &gt; 200_000 else \"\u043e\u043a\",          f\"| \u0442\u0435\u043a\u0441\u0442 {text\/1000:.0f} KB ({text\/html:.0%} \u043e\u0442 \u0432\u0435\u0441\u0430)\")<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<pre><code>https:\/\/www.python.org\/ HTML 53 KB, \u043e\u043a | \u0442\u0435\u043a\u0441\u0442 7 KB (13% \u043e\u0442 \u0432\u0435\u0441\u0430)https:\/\/habr.com\/ru\/articles\/ HTML 327 KB, \u0448\u0442\u0440\u0430\u0444 | \u0442\u0435\u043a\u0441\u0442 36 KB (11% \u043e\u0442 \u0432\u0435\u0441\u0430)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u041b\u0438\u0441\u0442\u0438\u043d\u0433 \u0441\u0442\u0430\u0442\u0435\u0439 \u0425\u0430\u0431\u0440\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043e \u00ab\u0442\u044f\u0436\u0451\u043b\u043e\u043c HTML\u00bb \u043f\u0440\u0438 36 \u041a\u0411 \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430. \u0414\u043e\u043b\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u0443 \u043e\u0431\u0435\u0438\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u043e\u043a\u043e\u043b\u043e 12 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043e\u0432. \u041c\u043e\u0434\u0435\u043b\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u043f\u043e\u0441\u043b\u0435 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0448\u0442\u0440\u0430\u0444 \u043f\u043e \u0441\u044b\u0440\u044b\u043c \u0431\u0430\u0439\u0442\u0430\u043c \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0435. \u041f\u043e\u0440\u043e\u0433 \u0441\u0442\u043e\u0438\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u043c \u0438 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0438\u0437\u0432\u043b\u0435\u0447\u0451\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 \u043a \u0432\u0435\u0441\u0443 HTML: \u043e\u043d\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u0435\u0442 \u00ab\u0442\u044f\u0436\u0451\u043b\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443\u00bb \u0438 \u00ab\u0442\u044f\u0436\u0451\u043b\u0443\u044e \u043e\u0431\u0432\u044f\u0437\u043a\u0443 \u0432\u043e\u043a\u0440\u0443\u0433 \u0442\u043e\u043d\u043a\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430\u00bb, \u0430 \u044d\u0442\u043e \u0440\u0430\u0437\u043d\u044b\u0435 \u0434\u0438\u0430\u0433\u043d\u043e\u0437\u044b.<\/p>\n<h3>\u041d\u0430\u0445\u043e\u0434\u043a\u0430 6: \u0444\u043b\u0430\u0433 &#8212;lang \u043d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u0438 \u0431\u0435\u0437 \u044d\u0444\u0444\u0435\u043a\u0442\u0430<\/h3>\n<p><code>cli\/main.py<\/code>, \u0446\u0438\u0442\u0430\u0442\u0430 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0430:<\/p>\n<pre><code class=\"python\">@click.group()@click.option(\"--lang\", default=None, envvar=\"GEO_LANG\",              type=click.Choice([\"it\", \"en\"], case_sensitive=False),              help=\"Lingua output: it (default), en\")def cli(lang):    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u041e\u043f\u0446\u0438\u044f \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0430 \u043d\u0430 \u0433\u0440\u0443\u043f\u043f\u0435, \u0430 \u043d\u0435 \u043d\u0430 \u043f\u043e\u0434\u043a\u043e\u043c\u0430\u043d\u0434\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u044b\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 (\u0432\u044b\u0432\u043e\u0434 \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043e\u0431\u0440\u0435\u0437\u0430\u043d \u0434\u043e \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438, \u0434\u0430\u043b\u044c\u0448\u0435 \u0438\u0434\u0451\u0442 \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0430):<\/p>\n<pre><code class=\"bash\">$ geo audit --lang en --url https:\/\/example.comUsage: geo audit [OPTIONS]Try 'geo audit --help' for help.Error: No such option '--lang'.$ geo --lang en audit --help 2&gt;&amp;1 | head -1Note: --lang=en accepted. Full CLI localization is planned for a future release; output is currently in English regardless of this flag.<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u0447\u0435\u0441\u0442\u043d\u043e\u0435: \u0444\u0430\u0439\u043b\u044b <code>.mo<\/code> \u0432 <code>i18n\/locales\/<\/code> \u043b\u0435\u0436\u0430\u0442 \u0434\u043b\u044f <code>it<\/code> \u0438 <code>en<\/code>, \u043d\u043e \u0441\u0442\u0440\u043e\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 gettext \u043d\u0435 \u043f\u0440\u043e\u0433\u043d\u0430\u043d\u044b, \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>_<\/code> \u0438\u0437 <code>i18n<\/code> \u043d\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u0433\u0434\u0435. \u0414\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 \u044f\u0437\u044b\u043a \u0438\u0442\u0430\u043b\u044c\u044f\u043d\u0441\u043a\u0438\u0439 (<code>DEFAULT_LANG = \"it\"<\/code>, \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0438\u0437 <code>GEO_LANG<\/code>), \u0432\u044b\u0431\u043e\u0440 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d <code>it<\/code> \u0438 <code>en<\/code>. \u0412 \u0434\u043e\u043a\u0441\u0442\u0440\u043e\u043a\u0435 \u043c\u043e\u0434\u0443\u043b\u044f <code>i18n<\/code> \u043a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0435\u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a, <code>geo audit --lang en<\/code>. \u041b\u0435\u0447\u0438\u0442\u0441\u044f \u0434\u0443\u0431\u043b\u0435\u043c \u043e\u043f\u0446\u0438\u0438 \u0443 \u043f\u043e\u0434\u043a\u043e\u043c\u0430\u043d\u0434 \u0438\u043b\u0438 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u043e\u0439 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430, \u0430 \u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u0434\u043e\u043a\u0441\u0442\u0440\u043e\u043a\u0435 \u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u0441 \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u043c.<\/p>\n<h3>\u0427\u0442\u043e \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442<\/h3>\n<p>\u041f\u044f\u0442\u044c \u043d\u0430\u0445\u043e\u0434\u043e\u043a \u0438\u0437 \u0448\u0435\u0441\u0442\u0438 \u044d\u0442\u043e \u043d\u0435 \u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u043a\u043e\u0434: \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0447\u0438\u0441\u043b\u0430 \u043f\u0435\u0447\u0430\u0442\u0430\u044e\u0442\u0441\u044f, \u0432\u044b\u0432\u043e\u0434 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e. \u0420\u0430\u0441\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0441\u043c\u044b\u0441\u043b. \u0414\u043e\u043b\u044f \u0431\u044b\u0432\u0430\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u0435\u0434\u0438\u043d\u0438\u0446\u044b, \u0431\u0430\u043b\u043b 0-100 \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0434\u0432\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438, \u043d\u0430\u043f\u0435\u0447\u0430\u0442\u0430\u043d\u043d\u044b\u0435 \u0440\u044f\u0434\u043e\u043c \u0432 \u0442\u043e\u0439 \u0436\u0435 \u0448\u043a\u0430\u043b\u0435, \u0430 \u043d\u043e\u043b\u044c \u0432 \u0431\u0430\u0442\u0447\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u00ab\u0441\u0435\u0440\u0432\u0435\u0440 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435 \u0434\u0435\u0441\u044f\u0442\u0438 \u0441\u0435\u043a\u0443\u043d\u0434 \u043d\u0430 \u043f\u044f\u0442\u043d\u0430\u0434\u0446\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432\u00bb.<\/p>\n<p>\u0427\u0435\u0442\u044b\u0440\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u043f\u043e\u0445\u043e\u0436\u0438\u0439 \u043a\u043e\u0434, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0432\u0430\u0448 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439:<\/p>\n<ul>\n<li>\n<p><code>find_all<\/code> \u043f\u043e \u043d\u0430\u0431\u043e\u0440\u0443 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0442\u0435\u0433\u043e\u0432 \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 \u0434\u0432\u0430\u0436\u0434\u044b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0435 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c ratio \u043d\u0443\u0436\u043d\u044b \u0434\u0435\u0434\u0443\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0443\u0437\u043b\u043e\u0432 \u0438 <code>min(..., 1.0)<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u043b\u0430\u0442\u0438\u043d\u0441\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 <code>[A-Z]<\/code> \u0432 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0435 \u043e\u0431\u043d\u0443\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u0440\u0438\u043a\u0443 \u043d\u0430 \u043d\u0435\u043b\u0430\u0442\u0438\u043d\u0441\u043a\u043e\u043c \u0442\u0435\u043a\u0441\u0442\u0435 \u043c\u043e\u043b\u0447\u0430, \u0431\u0435\u0437 \u043e\u0448\u0438\u0431\u043a\u0438 \u0438 \u0431\u0435\u0437 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>\u0443 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u043e\u0433\u043e \u0431\u0430\u043b\u043b\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0432\u0435\u0441\u043e\u0432 \u0438 \u0442\u0435\u0441\u0442 \u043d\u0430 \u0441\u0443\u043c\u043c\u0443, \u0430 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u0432 \u0442\u043e\u0439 \u0436\u0435 \u0448\u043a\u0430\u043b\u0435 0-100 \u0440\u044f\u0434\u043e\u043c \u0441 \u0438\u0442\u043e\u0433\u043e\u043c \u0447\u0438\u0442\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u044c;<\/p>\n<\/li>\n<li>\n<p>\u0442\u0430\u0439\u043c\u0430\u0443\u0442, \u043d\u0430\u0432\u0435\u0448\u0435\u043d\u043d\u044b\u0439 \u043d\u0430 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0432\u043c\u0435\u0441\u0442\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u00ab\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e\u00bb \u0432 \u00ab\u043d\u043e\u043b\u044c\u00bb, \u0430 \u0444\u043b\u0430\u0433 concurrency \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u0440\u0430\u0442\u044c \u043e \u0447\u0438\u0441\u043b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u043f\u043e\u043b\u0451\u0442\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u044d\u0442\u043e\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0443\u0436\u0435 \u0432 \u0440\u0430\u0431\u043e\u0442\u0435:<\/p>\n<ul>\n<li>\n<p>\u0432 \u0431\u0430\u0442\u0447\u0435 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <code>error<\/code> \u0440\u0430\u043d\u044c\u0448\u0435, \u0447\u0435\u043c <code>score<\/code>: <code>Timeout (10s)<\/code> \u0438 <code>0<\/code> \u0432 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u044d\u0442\u043e \u043d\u0435 \u043e\u0446\u0435\u043d\u043a\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b;<\/p>\n<\/li>\n<li>\n<p><code>boilerplate_ratio<\/code> \u0447\u0438\u0442\u0430\u0442\u044c \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0444\u0430\u043a\u0442\u043e\u043c \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a\u0430: \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u043a\u043e\u043b\u043e \u0435\u0434\u0438\u043d\u0438\u0446\u044b \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0431\u0435\u0437 <code>main<\/code> \u044d\u0442\u043e \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442 \u0432\u0435\u0442\u043a\u0438, \u0430 \u043d\u0435 99 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043e\u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0430;<\/p>\n<\/li>\n<li>\n<p><code>chunk_readiness_score<\/code> \u0438 <code>context_window<\/code> \u043d\u0435 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0441 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u043c \u0431\u0430\u043b\u043b\u043e\u043c;<\/p>\n<\/li>\n<li>\n<p>\u0434\u043b\u044f \u0440\u0443\u0441\u0441\u043a\u0438\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0442\u0435\u043a\u0441\u0442\u0430 \u0437\u0430\u0448\u0438\u0442\u0430 \u043f\u043e\u0434 \u043b\u0430\u0442\u0438\u043d\u0438\u0446\u0443 \u0438 \u043d\u0435 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442.<\/p>\n<\/li>\n<\/ul>\n<p>\u0427\u0435\u0442\u044b\u0440\u0435 \u043f\u0440\u0430\u0432\u043a\u0438 \u0438\u0437 \u0448\u0435\u0441\u0442\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435: \u043a\u0438\u0440\u0438\u043b\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0432 \u0434\u0432\u0443\u0445 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0430\u0445, <code>min(..., 1.0)<\/code> \u0438 \u0444\u0438\u043b\u044c\u0442\u0440 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u043e\u0432 \u0432 \u043e\u0434\u043d\u043e\u0439 \u0432\u0435\u0442\u043a\u0435, \u0434\u0432\u0430 \u0447\u0438\u0441\u043b\u0430 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433, \u0434\u0443\u0431\u043b\u044c \u043e\u043f\u0446\u0438\u0438 \u0443 \u043f\u043e\u0434\u043a\u043e\u043c\u0430\u043d\u0434. \u0414\u0432\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u0440\u0443\u043f\u043d\u0435\u0435: \u0435\u0434\u0438\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0432\u0435\u0441\u043e\u0432 \u0441\u043e \u0448\u0442\u0440\u0430\u0444\u043e\u043c \u0438 \u0444\u043b\u0430\u0433 \u043e\u0442\u043c\u0435\u043d\u044b \u0434\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a. \u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f MIT, \u0442\u0430\u043a \u0447\u0442\u043e \u044d\u0442\u043e \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u044b \u0432 pull request, \u0430 \u043d\u0435 \u043f\u043e\u0432\u043e\u0434 \u0438\u0441\u043a\u0430\u0442\u044c \u0437\u0430\u043c\u0435\u043d\u0443.<\/p>\n<h3>\u0427\u0435\u0433\u043e \u044d\u0442\u043e\u0442 \u0440\u0430\u0437\u0431\u043e\u0440 \u043d\u0435 \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u0442<\/h3>\n<ul>\n<li>\n<p>\u041a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u044e \u0431\u0430\u043b\u043b\u0430 \u0441 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0446\u0438\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u044f \u043d\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u043b: \u0440\u0430\u0437\u0431\u043e\u0440 \u043f\u0440\u043e \u0442\u043e, \u0447\u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u043a\u043e\u0434, \u0438 \u043d\u0435 \u043f\u0440\u043e \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u043e\u0442\u0432\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043c\u043e\u0442\u0440\u0435\u043b \u043e\u0434\u043d\u0443 \u0432\u0435\u0440\u0441\u0438\u044e, 4.18.2, \u043d\u0430 Python 3.11.13. \u0412 \u0434\u0440\u0443\u0433\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432\u0435\u0442\u043a\u0438 \u043c\u043e\u0433\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u0448\u0435\u0441\u0442\u044c \u043d\u0430\u0445\u043e\u0434\u043e\u043a \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c, \u043d\u043e \u043d\u0430 \u0441\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0445, \u0434\u0432\u0443\u0445 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0435, \u0430 \u043d\u0435 \u043d\u0430 \u0432\u044b\u0431\u043e\u0440\u043a\u0435 \u0441\u0430\u0439\u0442\u043e\u0432. \u0418\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u00ab\u0441\u0443\u043c\u043c\u0430 \u0432\u0435\u0441\u043e\u0432 \u0440\u043e\u0432\u043d\u043e 100\u00bb \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b, \u0430 \u043d\u0435 \u0442\u0435\u0441\u0442\u043e\u043c \u043f\u0430\u043a\u0435\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0427\u0438\u0441\u043b\u0430 \u0441 \u0436\u0438\u0432\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0434\u0440\u0435\u0439\u0444\u0443\u044e\u0442 \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u043e\u0433\u043e\u043d\u0430\u043c\u0438. \u0421\u0435\u0433\u043e\u0434\u043d\u044f python.org \u0434\u0430\u0451\u0442 <code>boilerplate_ratio<\/code> 0.65 \u0438 <code>chunk_readiness_score<\/code> 47, \u0432 \u043f\u0440\u043e\u0433\u043e\u043d\u0430\u0445 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0434\u043d\u044f\u043c\u0438 \u0440\u0430\u043d\u044c\u0448\u0435 \u0442\u0430\u043c \u0431\u044b\u043b\u043e 0.68 \u0438 45; \u0432\u0435\u0441 \u043b\u0438\u0441\u0442\u0438\u043d\u0433\u0430 \u0425\u0430\u0431\u0440\u0430 \u0443 \u043c\u0435\u043d\u044f \u0445\u043e\u0434\u0438\u043b \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 327-337 \u041a\u0411, \u0431\u0430\u0442\u0447 \u043d\u0430 \u0431\u044b\u0441\u0442\u0440\u043e\u0439 \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0435 0.2-0.5 \u0441. \u0421\u0432\u0435\u0440\u044f\u0442\u044c \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u044b, \u0430 \u043d\u0435 \u0446\u0438\u0444\u0440\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0443\u0442\u0438 (<code>--cache<\/code>) \u044f \u043d\u0435 \u0437\u0430\u043c\u0435\u0440\u044f\u043b, \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b.<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1090466\/\">https:\/\/habr.com\/ru\/articles\/1090466\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043a\u043b\u0430\u0441\u0441\u0430 GEO (\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u043f\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u044b \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439) \u0432\u044b\u0434\u0430\u044e\u0442 \u0431\u0430\u043b\u043b \u043e\u0442 0 \u0434\u043e 100 \u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439. \u0411\u0430\u043b\u043b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0430\u043a \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0435 \u0438 \u0443\u0435\u0437\u0436\u0430\u0435\u0442 \u0432 \u0442\u0438\u043a\u0435\u0442\u044b \u0438 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b.\u042f \u0432\u0437\u044f\u043b \u043e\u0434\u0438\u043d \u0442\u0430\u043a\u043e\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, geo-optimizer-skill (PyPI, MIT, \u0430\u0432\u0442\u043e\u0440 Juan Camilo Auriti, \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 auriti-labs\/geo-optimizer-skill), CLI \u0432\u0435\u0440\u0441\u0438\u0438 4.18.2, \u0438 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b, \u0438\u0437 \u0447\u0435\u0433\u043e \u0431\u0430\u043b\u043b \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f. \u041f\u043e\u0432\u043e\u0434\u043e\u043c \u0441\u0442\u0430\u043b \u0431\u0430\u0442\u0447: \u043f\u0440\u043e\u0433\u043e\u043d \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u0434\u0435\u0441\u044f\u0442\u043a\u0430\u043c \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0432\u0435\u0440\u043d\u0443\u043b \u043d\u0443\u043b\u0438 \u043f\u043e \u0432\u0441\u0435\u043c. \u042f \u043f\u043e\u043b\u0435\u0437 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u043a\u0430\u043a \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u043b\u044c, \u0438 \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u0447\u0438\u0442\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435.\u041f\u0435\u0440\u0432\u043e\u0435, \u0447\u0442\u043e \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u043f\u043e \u0434\u043e\u0440\u043e\u0433\u0435: \u043c\u0435\u0442\u0440\u0438\u043a\u0430 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u00ab\u0434\u043e\u043b\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u00bb \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 1.73 \u043d\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435 \u0438\u0437 \u043c\u0435\u043d\u044e, \u043e\u0434\u043d\u043e\u0433\u043e \u0430\u0431\u0437\u0430\u0446\u0430 \u0438 \u043f\u043e\u0434\u0432\u0430\u043b\u0430. \u041a\u043e\u0434 \u0432 \u043d\u0430\u0445\u043e\u0434\u043a\u0435 1, \u0432\u044b\u0432\u043e\u0434 \u0434\u043e\u0441\u043b\u043e\u0432\u043d\u043e \u0442\u0430\u043a\u043e\u0439.\u043c\u0438\u043d\u0438: \u043f\u0430\u043a\u0435\u0442 ratio 1.73, \u0444\u043b\u0430\u0433 True | \u043f\u0440\u0430\u0432\u043a\u0430 ratio 0.87, \u0444\u043b\u0430\u0433 True | \u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442 60 \u0437\u043d\u0430\u043a\u043e\u0432\u041e\u0434\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u043f\u0430\u043a\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 robots.txt, llms.txt \u0438 \u0447\u0435\u0442\u044b\u0440\u0435 \u0442\u043e\u0447\u043a\u0438 AI-\u0434\u0438\u0441\u043a\u0430\u0432\u0435\u0440\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u043d\u0430\u0447\u0435 \u0441\u043c\u043e\u0442\u0440\u0438\u0448\u044c \u0440\u0443\u043a\u0430\u043c\u0438 \u043f\u043e \u043e\u0434\u043d\u043e\u0439, \u0430 \u043a\u043e\u0434 \u0440\u0430\u0437\u043b\u043e\u0436\u0435\u043d \u043f\u043e \u0444\u0430\u0439\u043b\u0443 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443, \u0442\u0430\u043a \u0447\u0442\u043e \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u043e\u0447\u043d\u043e. \u041d\u0438\u0436\u0435 \u0448\u0435\u0441\u0442\u044c \u043c\u0435\u0441\u0442, \u0433\u0434\u0435 \u043d\u0430\u043f\u0435\u0447\u0430\u0442\u0430\u043d\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0437\u043d\u0430\u0447\u0438\u0442 \u043d\u0435 \u0442\u043e, \u0447\u0442\u043e \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0441 \u0445\u043e\u0434\u0443, \u0438 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e \u043f\u043e\u0447\u0438\u043d\u043a\u0435 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0435. \u0420\u0430\u0437\u0431\u043e\u0440 \u043d\u0443\u0436\u0435\u043d, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u043a\u0430\u043a\u0443\u044e \u0438\u043c\u0435\u043d\u043d\u043e \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443 \u0432\u044b \u0447\u0438\u0442\u0430\u0435\u0442\u0435.\u041a\u0430\u043a \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438\u041f\u0430\u043a\u0435\u0442 \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044f \u043a\u0430\u043a \u0443\u0442\u0438\u043b\u0438\u0442\u0430, \u0444\u0430\u0439\u043b\u044b \u043b\u0435\u0436\u0430\u0442 \u0432 \u0435\u0451 venv:uv tool install &#171;geo-optimizer-skill[mcp]&#187;PY=$(uv tool dir)\/geo-optimizer-skill\/bin\/pythonGEO=$($PY -c &#8216;import geo_optimizer, pathlib; print(pathlib.Path(geo_optimizer.__file__).parent)&#8217;)ls $GEO   # cli core i18n mcp models skills utils web, \u043f\u043b\u044e\u0441 __init__.py, py.typed, __pycache__\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432 core\/, \u043f\u043e \u0444\u0430\u0439\u043b\u0443 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443; \u0432\u0435\u0441\u0430 \u0438 \u043f\u043e\u0440\u043e\u0433\u0438 \u0432 models\/config.py, \u0441\u0431\u043e\u0440\u043a\u0430 \u0431\u0430\u043b\u043b\u0430 \u0432 core\/scoring.py. \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043d\u0438\u0436\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0438\u0441\u044c \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c $PY (3.11.13): \u0432 \u0435\u0433\u043e venv \u0443\u0436\u0435 \u0441\u0442\u043e\u044f\u0442 beautifulsoup4 4.15.0 \u0438 httpx 0.28.1. \u0417\u0430\u043c\u0435\u0440\u044b \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0441\u0434\u0435\u043b\u0430\u043d\u044b 02.10.2026.\u041d\u0430\u0445\u043e\u0434\u043a\u0430 1: \u0434\u043e\u043b\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u044b\u0432\u0430\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u0435\u0434\u0438\u043d\u0438\u0446\u044bcore\/audit_negative.py, \u0446\u0438\u0442\u0430\u0442\u0430 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0430, \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u0443\u0431\u0440\u0430\u043d\u044b (\u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0441\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f):main_content = text_soup.find(&#171;main&#187;) or text_soup.find(&#171;article&#187;) or text_soup.find(attrs={&#171;role&#187;: &#171;main&#187;})if main_content and total_text_len &gt; 0:    result.boilerplate_ratio = round(1.0 &#8212; (main_text_len \/ total_text_len), 2)elif total_text_len &gt; 0:    nav_footer_len = 0    for tag in text_soup.find_all([&#171;nav&#187;, &#171;footer&#187;, &#171;header&#187;]):        nav_footer_len += len(tag.get_text(separator=&#187; &#171;, strip=True))    if nav_footer_len &gt; 0:        result.boilerplate_ratio = round(nav_footer_len \/ total_text_len, 2)\u0412\u0435\u0442\u043a\u0438 \u0441\u0447\u0438\u0442\u0430\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0432\u0435\u0449\u0438. \u041b\u0435\u043d\u0434\u043c\u0430\u0440\u043a (main, article, role=&#187;main&#187;) \u043d\u0430\u0439\u0434\u0435\u043d: \u0434\u043e\u043b\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u044d\u0442\u043e \u00ab\u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442 \u043c\u0438\u043d\u0443\u0441 \u0442\u0435\u043a\u0441\u0442 \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a\u0430\u00bb. \u041b\u0435\u043d\u0434\u043c\u0430\u0440\u043a\u0430 \u043d\u0435\u0442: \u044d\u0442\u043e \u0441\u0443\u043c\u043c\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432\u0441\u0435\u0445 nav, footer, header, \u0434\u0435\u043b\u0451\u043d\u043d\u0430\u044f \u043d\u0430 \u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.\u0412\u0442\u043e\u0440\u0430\u044f \u0432\u0435\u0442\u043a\u0430 \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043e\u043b\u0435\u0439 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f. find_all([&#171;nav&#187;, &#171;footer&#187;, &#171;header&#187;]) \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438 header, \u0438 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0439 \u0432 \u043d\u0435\u0433\u043e nav, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0435\u043a\u0441\u0442 \u043c\u0435\u043d\u044e \u0432\u0445\u043e\u0434\u0438\u0442 \u0432 \u0441\u0443\u043c\u043c\u0443 \u0434\u0432\u0430\u0436\u0434\u044b. \u041f\u043e\u0442\u043e\u043b\u043a\u0430 \u043d\u0435\u0442, \u0430 boilerplate_high \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443 \u0441 BOILERPLATE_RATIO_THRESHOLD = 0.6. \u0424\u043b\u0430\u0433 \u0438\u0434\u0451\u0442 \u0432 signals_found, \u0442\u043e\u0442 \u0437\u0430\u0434\u0430\u0451\u0442 severity, \u0430 severity \u0434\u0430\u0451\u0442 \u0448\u0442\u0440\u0430\u0444 \u043a \u0431\u0430\u043b\u043b\u0443: \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442 \u0434\u043e\u0435\u0437\u0436\u0430\u0435\u0442 \u0434\u043e \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0439 \u0446\u0438\u0444\u0440\u044b.\u0414\u0432\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430, \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u0434\u0432\u043e\u0439\u043d\u043e\u0439 \u0441\u0447\u0451\u0442 \u043f\u0435\u0440\u0435\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u0435\u0440\u0434\u0438\u043a\u0442:from bs4 import BeautifulSoupfrom geo_optimizer.core.audit_negative import audit_negative_signalsfrom geo_optimizer.models.results import ContentResult, MetaResult, SchemaResultMENU = &#171;\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0420\u0430\u0437\u0434\u0435\u043b\u044b \u0410\u0440\u0445\u0438\u0432 \u0422\u0435\u0433\u0438&#187;mini = (&#171;&lt;html&gt;&lt;body&gt;&lt;header&gt;&lt;nav&gt;&#187; + MENU + &#171;&lt;\/nav&gt;&lt;\/header&gt;&lt;p&gt;\u0422\u0435\u043a\u0441\u0442.&lt;\/p&gt;&#187;        &#171;&lt;footer&gt;&lt;nav&gt;&#187; + MENU + &#171;&lt;\/nav&gt;&lt;\/footer&gt;&lt;\/body&gt;&lt;\/html&gt;&#187;)page = mini.replace(&#171;&lt;p&gt;\u0422\u0435\u043a\u0441\u0442.&lt;\/p&gt;&#187;, &#171;&lt;p&gt;\u041a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 \u0430\u0431\u0437\u0430\u0446 \u043f\u0440\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0444\u043e\u0440\u043c\u0443\u043b\u044b.&lt;\/p&gt;&#187;)def fallback_fixed(s):    total = len(s.get_text(&#187; &#171;, True))    tops = [t for t in s.find_all([&#171;nav&#187;, &#171;footer&#187;, &#171;header&#187;])            if t.find_parent([&#171;nav&#187;, &#171;footer&#187;, &#171;header&#187;]) is None]    boiler = sum(len(t.get_text(&#187; &#171;, True)) for t in tops)    return round(min(boiler \/ total, 1.0), 2) if total else 0.0for name, html in ((&#171;\u043c\u0438\u043d\u0438&#187;, mini), (&#171;\u0432\u0442\u043e\u0440\u043e\u0439&#187;, page)):    s = BeautifulSoup(html, &#171;html.parser&#187;)    r = audit_negative_signals(s, html, ContentResult(), MetaResult(), SchemaResult(),                               soup_clean=s).boilerplate_ratio    f = fallback_fixed(s)    print(f&#187;{name}: \u043f\u0430\u043a\u0435\u0442 ratio {r}, \u0444\u043b\u0430\u0433 {r &gt; 0.6} | \u043f\u0440\u0430\u0432\u043a\u0430 ratio {f}, \u0444\u043b\u0430\u0433 {f &gt; 0.6} |&#187;          f&#187; \u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442 {len(s.get_text(&#8216; &#8216;, True))} \u0437\u043d\u0430\u043a\u043e\u0432&#187;)\u043c\u0438\u043d\u0438: \u043f\u0430\u043a\u0435\u0442 ratio 1.73, \u0444\u043b\u0430\u0433 True | \u043f\u0440\u0430\u0432\u043a\u0430 ratio 0.87, \u0444\u043b\u0430\u0433 True | \u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442 60 \u0437\u043d\u0430\u043a\u043e\u0432\u0432\u0442\u043e\u0440\u043e\u0439: \u043f\u0430\u043a\u0435\u0442 ratio 1.13, \u0444\u043b\u0430\u0433 True | \u043f\u0440\u0430\u0432\u043a\u0430 ratio 0.57, \u0444\u043b\u0430\u0433 False | \u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442 92 \u0437\u043d\u0430\u043a\u043e\u0432\u0412 \u043f\u0435\u0440\u0432\u043e\u043c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435 \u043c\u0435\u043d\u044e 26 \u0437\u043d\u0430\u043a\u043e\u0432, \u0443\u0437\u043b\u043e\u0432 \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u0447\u0435\u0442\u044b\u0440\u0435 (header, nav, footer, nav), 26 * 4 = 104 \u043f\u0440\u0438 60 \u0437\u043d\u0430\u043a\u0430\u0445 \u0442\u0435\u043a\u0441\u0442\u0430, \u043e\u0442\u0441\u044e\u0434\u0430 1.73. \u0412\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u043e\u0434\u043d\u0430 \u0438 \u0442\u0430 \u0436\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043f\u043e \u043a\u043e\u0434\u0443 \u043f\u0430\u043a\u0435\u0442\u0430 \u00ab\u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u043c\u00bb, \u0430 \u043f\u0440\u0438 \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u0435 \u0431\u0435\u0437 \u0434\u0432\u043e\u0439\u043d\u043e\u0433\u043e \u0441\u0447\u0451\u0442\u0430 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043d\u0438\u0436\u0435 \u043f\u043e\u0440\u043e\u0433\u0430.\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432 \u043f\u0430\u043a\u0435\u0442\u0435 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c: detect_boilerplate_ratio \u0432 core\/citability.py \u0443\u0431\u0438\u0440\u0430\u0435\u0442 nav, header \u0438 footer \u0447\u0435\u0440\u0435\u0437 decompose, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0432\u043e\u0439\u043d\u043e\u0433\u043e \u0441\u0447\u0451\u0442\u0430 \u0442\u0430\u043c \u043d\u0435\u0442, \u0430 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0435\u0439 \u043f\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044e. \u041d\u0430 \u0442\u0435\u0445 \u0436\u0435 \u0434\u0432\u0443\u0445 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0445 \u043e\u043d\u0430 \u043f\u0435\u0447\u0430\u0442\u0430\u0435\u0442 \u0434\u043e\u043b\u044e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 0.1 \u0438 0.41, \u0442\u043e \u0435\u0441\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d 0.9 \u0438 0.59, \u0438 \u0432\u0442\u043e\u0440\u043e\u0435 \u0441\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0441 fallback_fixed. \u041e\u0431\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0433\u043e\u043d\u0435 geo audit: core\/audit.py \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 audit_citability \u0440\u044f\u0434\u043e\u043c \u0441 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430\u043c\u0438. \u041d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 python.org \u043f\u0435\u0440\u0432\u0430\u044f \u043f\u0435\u0447\u0430\u0442\u0430\u0435\u0442 \u0434\u043e\u043b\u044e \u0448\u0430\u0431\u043b\u043e\u043d\u0430 0.65, \u0442\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 35 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043e\u0432, \u0432\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u043b\u044e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 0.03 (\u043e\u043d\u0430 \u043d\u0435 \u0441\u043c\u043e\u0442\u0440\u0438\u0442 role=&#187;main&#187; \u0438 \u0443\u0445\u043e\u0434\u0438\u0442 \u0432 \u044d\u0432\u0440\u0438\u0441\u0442\u0438\u043a\u0443). \u041d\u0430 \u043b\u0438\u0441\u0442\u0438\u043d\u0433\u0435 \u0441\u0442\u0430\u0442\u0435\u0439 \u0425\u0430\u0431\u0440\u0430 \u043e\u0431\u0435 \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u044b: 0.02 \u0438 0.98.\u0423 \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a-\u0432\u0435\u0442\u043a\u0438 \u0441\u0432\u043e\u044f \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c: \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u043c \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u0441\u0451 \u0432\u043d\u0435 \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a\u0430, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0445 \u0441\u0435\u043a\u0446\u0438\u0439.# \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430from geo_optimizer.utils.http import fetch_urlfor url in (&#171;https:\/\/www.python.org\/&#187;, &#171;https:\/\/habr.com\/ru\/articles\/&#187;):    raw = fetch_url(url)[0].text or &#171;&#187;    soup = BeautifulSoup(raw, &#171;html.parser&#187;)    for t in soup([&#171;script&#187;, &#171;style&#187;, &#171;noscript&#187;, &#171;template&#187;]):        t.decompose()    lm = soup.find(&#171;main&#187;) or soup.find(&#171;article&#187;) or soup.find(attrs={&#171;role&#187;: &#171;main&#187;})    r = audit_negative_signals(soup, raw, ContentResult(), MetaResult(), SchemaResult(),                               soup_clean=soup).boilerplate_ratio    print(url, &#171;| \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a:&#187;, lm.name if lm else None, &#171;| ratio:&#187;, r)https:\/\/www.python.org\/ | \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a: section | ratio: 0.65https:\/\/habr.com\/ru\/articles\/ | \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a: main | ratio: 0.02\u041d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 python.org \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a \u044d\u0442\u043e section role=&#187;main&#187; \u043b\u0438\u0448\u044c \u0441 \u0447\u0430\u0441\u0442\u044c\u044e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430, \u043d\u0430 \u043b\u0438\u0441\u0442\u0438\u043d\u0433\u0435 \u0425\u0430\u0431\u0440\u0430 \u0432 main \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430. \u0420\u0430\u0437\u043d\u0438\u0446\u0430 \u0432 \u0442\u0440\u0438\u0434\u0446\u0430\u0442\u044c \u0440\u0430\u0437 \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438 \u0441\u043e \u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u0430\u0440\u043a\u0430\u0441\u043e\u043c (\u0448\u0430\u043f\u043a\u0430, \u043f\u043e\u0434\u0432\u0430\u043b, \u043f\u043e\u0442\u043e\u043a \u0431\u043b\u043e\u043a\u043e\u0432) \u0437\u0430\u0434\u0430\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u043c, \u0447\u0442\u043e \u0442\u0435\u043c\u0430 \u043f\u043e\u043b\u043e\u0436\u0438\u043b\u0430 \u0432 \u043b\u0435\u043d\u0434\u043c\u0430\u0440\u043a.\u041b\u0435\u0447\u0438\u0442\u0441\u044f \u0442\u0430\u043a: \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c detect_boilerplate_ratio \u0432\u043c\u0435\u0441\u0442\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0432\u0435\u0442\u043a\u0438 \u0432 audit_negative.py. \u0415\u0441\u043b\u0438 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0434\u0432\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0442\u043e \u0432 \u0437\u0430\u043f\u0430\u0441\u043d\u043e\u0439 \u0432\u0435\u0442\u043a\u0435 \u0431\u0440\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0440\u0445\u043d\u0435\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 \u0443\u0437\u043b\u044b (\u043a\u0430\u043a \u0432 fallback_fixed) \u043b\u0438\u0431\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0443\u0437\u043b\u043e\u0432 \u043f\u0435\u0440\u0435\u0434 \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u043e\u043c \u0434\u043b\u0438\u043d\u044b, \u043f\u043b\u044e\u0441 min(&#8230;, 1.0), \u0447\u0442\u043e\u0431\u044b \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c ratio \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u0430\u0441\u044c \u0434\u043e\u043b\u0435\u0439.\u041d\u0430\u0445\u043e\u0434\u043a\u0430 2: \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0437\u043d\u0430\u044e\u0442 \u043a\u0438\u0440\u0438\u043b\u043b\u0438\u0446\u044bcore\/audit_rag.py, \u0446\u0438\u0442\u0430\u0442\u0430 \u043a\u0430\u043a \u0432 \u043f\u0430\u043a\u0435\u0442\u0435:_DEFINITION_RE = re.compile(    r&#187;^[A-Z][^.]{5,60}\\b(?:is|are|refers?\\s+to|means?|describes?|represents?)\\b&#187;,    re.MULTILINE,)_ANCHOR_RE = re.compile(r&#187;(?&lt;=[.!?]\\s)[A-Z][^.!?]{30,200}[.!?]&#187;)\u041f\u0435\u0440\u0432\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043b\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c \u0432\u0438\u0434\u0430 \u00abX is Y\u00bb. \u0412\u0442\u043e\u0440\u0430\u044f \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u00ab\u044f\u043a\u043e\u0440\u043d\u044b\u0435\u00bb \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u0441\u0430\u043c\u043e\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u0435 \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f 30-200 \u0437\u043d\u0430\u043a\u043e\u0432 (\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u043d\u0430\u0434 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u043e\u0439 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u0431\u0435\u0449\u0430\u0435\u0442 \u00ab10-40 words\u00bb, \u0442\u043e \u0435\u0441\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u0448\u0430\u0431\u043b\u043e\u043d \u043c\u0435\u0440\u044f\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0435\u0434\u0438\u043d\u0438\u0446\u044b). \u041e\u0431\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0438\u0434\u0443\u0442 \u0432 chunk_readiness_score. \u041a\u043b\u0430\u0441\u0441 [A-Z] \u043a\u0438\u0440\u0438\u043b\u043b\u0438\u0446\u0443 \u043d\u0435 \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u0442, \u0430 \u0441\u0432\u044f\u0437\u043a\u0438 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438\u0435: \u00abX \u044d\u0442\u043e Y\u00bb, \u00ab\u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f\u00bb, \u00ab\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439\u00bb \u0432 \u0448\u0430\u0431\u043b\u043e\u043d \u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0442. \u0411\u0435\u0440\u0451\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043f\u0440\u044f\u043c\u043e \u0438\u0437 \u043f\u0430\u043a\u0435\u0442\u0430 \u0438 \u043e\u0434\u0438\u043d \u0442\u0435\u043a\u0441\u0442 \u0432 \u0434\u0432\u0443\u0445 \u044f\u0437\u044b\u043a\u0430\u0445:import refrom geo_optimizer.core.audit_rag import _ANCHOR_RE, _DEFINITION_REUP = &#171;A-Z\u0410-\u042f\u0401&#187;DEF_FIX = re.compile(    rf&#187;^[{UP}][^.]{{5,60}}(?:\\b(?:is|are|refers?\\s+to|means?|describes?|represents?)\\b&#187;    r&#187;|\\s(?:\u044d\u0442\u043e|\u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f|\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\\s+\u0441\u043e\u0431\u043e\u0439|\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442)\\b)&#187;, re.MULTILINE)ANCHOR_FIX = re.compile(rf&#187;(?&lt;=[.!?]\\s)[{UP}][^.!?]{{30,200}}[.!?]&#187;)ru = (&#171;\u0413\u0435\u043d\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u043f\u0440\u0438\u0451\u043c\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u043e\u0442\u0432\u0435\u0442 \u043c\u043e\u0434\u0435\u043b\u0438. &#187;      &#171;\u041c\u043e\u0434\u0435\u043b\u044c \u0437\u0430\u0431\u0438\u0440\u0430\u0435\u0442 \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c.&#187;)en = (&#171;Generative optimization is a set of techniques for landing in a model answer. &#187;      &#171;The model lifts a ready fragment of text from the page along with its source.&#187;)for name, text in ((&#171;ru&#187;, ru), (&#171;en&#187;, en)):    print(f&#187;{name}: \u043f\u0430\u043a\u0435\u0442 definition={bool(_DEFINITION_RE.search(text[:150]))} &#187;          f&#187;anchors={len(_ANCHOR_RE.findall(text))} | \u043f\u0440\u0430\u0432\u043a\u0430 &#187;          f&#187;definition={bool(DEF_FIX.search(text[:150]))} &#187;          f&#187;anchors={len(ANCHOR_FIX.findall(text))}&#187;)ru: \u043f\u0430\u043a\u0435\u0442 definition=False anchors=0 | \u043f\u0440\u0430\u0432\u043a\u0430 definition=True anchors=1en: \u043f\u0430\u043a\u0435\u0442 definition=True anchors=1 | \u043f\u0440\u0430\u0432\u043a\u0430 definition=True anchors=1\u041e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043f\u043e \u0441\u043c\u044b\u0441\u043b\u0443 \u0442\u0435\u043a\u0441\u0442: \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0438 \u043e\u0434\u0438\u043d \u044f\u043a\u043e\u0440\u044c, \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c \u043d\u043e\u043b\u044c \u044f\u043a\u043e\u0440\u0435\u0439 \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u0442. \u0412 _compute_score \u0438\u0437 \u0442\u043e\u0433\u043e \u0436\u0435 \u0444\u0430\u0439\u043b\u0430 \u044d\u0442\u043e 10 \u0431\u0430\u043b\u043b\u043e\u0432 \u0437\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0438 \u0434\u043e 10 \u0437\u0430 \u044f\u043a\u043e\u0440\u044f: \u0434\u043e \u043f\u044f\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 chunk_readiness_score \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0440\u0443\u0441\u0441\u043a\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0435\u0451 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430.\u041f\u043e\u0447\u0438\u043d\u043a\u0430: \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u0438\u0440\u0438\u043b\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438 \u0440\u0443\u0441\u0441\u043a\u0438\u0435 \u0441\u0432\u044f\u0437\u043a\u0438, \u043a\u0430\u043a \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u043b\u0438\u0431\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u044f\u0437\u044b\u043a \u0432 \u043a\u043e\u043d\u0444\u0438\u0433 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (.geo-optimizer.yml \u043f\u0430\u043a\u0435\u0442 \u0443\u0436\u0435 \u0447\u0438\u0442\u0430\u0435\u0442). \u0418 \u043f\u043e\u0431\u043e\u0447\u043d\u044b\u0439 \u044d\u0444\u0444\u0435\u043a\u0442 (?&lt;=[.!?]\\s): \u043f\u0435\u0440\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u044f\u043a\u043e\u0440\u0435\u043c \u043d\u0435 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043d\u0438\u043a\u043e\u0433\u0434\u0430, \u043e\u0442\u0441\u044e\u0434\u0430 \u043e\u0434\u0438\u043d \u044f\u043a\u043e\u0440\u044c \u043d\u0430 \u0434\u0432\u0430 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f.\u041d\u0430\u0445\u043e\u0434\u043a\u0430 3: \u0441\u0442\u043e \u0431\u0430\u043b\u043b\u043e\u0432 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0435 \u0438\u0437 \u0432\u0441\u0435\u0433\u043e, \u0447\u0442\u043e \u043f\u0435\u0447\u0430\u0442\u0430\u0435\u0442\u0441\u044fmodels\/config.py:CATEGORY_MAX = {    &#171;robots&#187;: 18, &#171;llms&#187;: 18, &#171;schema&#187;: 16, &#171;meta&#187;: 14,    &#171;content&#187;: 12, &#171;brand_entity&#187;: 10, &#171;signals&#187;: 6, &#171;ai_discovery&#187;: 6,}\u0421\u0443\u043c\u043c\u0430 \u0440\u043e\u0432\u043d\u043e 100. \u041d\u043e \u0432 \u0440\u0430\u0437\u0431\u0438\u0432\u043a\u0435 \u0438\u0437 core\/scoring.py \u0435\u0441\u0442\u044c \u043a\u043b\u044e\u0447, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0435 \u043d\u0435\u0442:from geo_optimizer.models.config import CATEGORY_MAXfrom geo_optimizer.core.scoring import compute_score_breakdownfrom geo_optimizer.models.results import (ContentResult, LlmsTxtResult, MetaResult,                                          RobotsResult, SchemaResult)keys = list(compute_score_breakdown(RobotsResult(),&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-497374","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/497374","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=497374"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/497374\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=497374"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=497374"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=497374"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}