0Pricing
AI Prompt Engineering · Урок

Запросы для извлечения именованных сущностей

Извлекайте имена, даты, местоположения и пользовательские сущности из неструктурированного текста

«Запросы для извлечения именованных сущностей» — бесплатный урок AI Prompt Engineering на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения AI Prompt Engineering, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс AI Prompt Engineering содержит 4 уроков всего.

Что такое извлечение именованных сущностей

Извлечение именованных сущностей (NER) — это задача выявления и категоризации конкретных объектов реального мира, упомянутых в тексте. Традиционная обработка естественного языка использует для NER статистические модели; LLM может выполнять эту задачу с помощью хорошо составленной инструкции.

Распространённые типы сущностей:

  • PERSON: имена людей (Elon Musk, Dr. Jane Smith)
  • ORG: компании и организации (Apple, WHO)
  • DATE: даты и выражения времени (January 15, last Tuesday, Q3 2024)
  • LOCATION: места (New York, the Amazon River)
  • MONEY: финансовые показатели ($4.2 billion)

Базовая инструкция для NER

Самая простая инструкция для NER запрашивает все сущности в определённом формате:

import anthropic, json

client = anthropic.Anthropic(api_key='YOUR_API_KEY')

text = 'Apple CEO Tim Cook met with European Commission President Ursula von der Leyen in Brussels on March 15, 2025 to discuss the Digital Markets Act.'

prompt = f'''
Extract all named entities from the text below.
Return ONLY a JSON object with no other text:
{{
  "people": ["string"],
  "organizations": ["string"],
  "locations": ["string"],
  "dates": ["string"]
}}

Text: {text}
'''

r = client.messages.create(
    model='claude-opus-4-5', max_tokens=300,
    messages=[{'role': 'user', 'content': prompt}]
)
print(json.loads(r.content[0].text))

Добавление ограничений типов при извлечении

Базовое извлечение возвращает строки сущностей. Ограничения типов добавляют проверку — они гарантируют, что даты имеют определённый формат, а названия организаций не содержат общеупотребительных слов:

prompt_typed = '''
Extract named entities from the text below with type constraints.
Return JSON:
{
  "people": ["Full name as written in text"],
  "organizations": ["Official organization name only, no articles (the, a)"],
  "dates": ["ISO 8601 format if possible: YYYY-MM-DD, else exact text as written"],
  "money": ["Include currency symbol and amount: $4.2B, EUR 500K"],
  "locations": ["City, Country format if applicable"]
}
If a category has no entities, use an empty array [].

Text: {text}
'''

print(prompt_typed[:200])
print('\nConstraints enforce consistent output format per entity type.')

Извлечение по схеме

Для использования в рабочих системах заранее определите схему сущностей и укажите её в инструкции. Это делает контракт выходных данных явным:

ENTITY_SCHEMA = '''
{
  "entities": [
    {
      "text": "exact text as it appears in the document",
      "type": "PERSON | ORG | DATE | LOCATION | MONEY | PRODUCT | EVENT",
      "normalized": "canonical form (e.g., full name, ISO date)",
      "start_char": "integer, character offset in source text",
      "confidence": "high | medium | low"
    }
  ]
}
'''

def extract_entities(text):
    prompt = f'Extract all named entities. Return JSON matching this schema exactly:\n{ENTITY_SCHEMA}\n\nText: {text}'
    r = client.messages.create(
        model='claude-opus-4-5', max_tokens=500,
        messages=[{'role': 'user', 'content': prompt}]
    )
    return json.loads(r.content[0].text)

result = extract_entities('Tesla stock rose 5% after Elon Musk announced the Cybertruck delivery on December 1.')
print(result['entities'][0])

Обработка неоднозначных сущностей

Некоторые строки сущностей неоднозначны: Apple может обозначать компанию или фрукт, а Jordan — человека или страну. Направьте модель на устранение неоднозначности с помощью контекста:

prompt_disambiguation = '''
Extract named entities from the text. For ambiguous entities, use the surrounding
context to determine the correct type. Include your reasoning in an "evidence" field.

Return JSON:
{
  "entities": [
    {
      "text": "string",
      "type": "PERSON | ORG | LOCATION | OTHER",
      "evidence": "brief reason for type assignment"
    }
  ]
}

Text: Jordan and Apple signed a distribution deal for the new Air Jordan shoes.
'''

# Expected output: Jordan = PERSON (context: Air Jordan), Apple = ORG (context: signed a deal)
print(prompt_disambiguation)

Извлечение с определениями полей

Для пользовательских типов сущностей, специфичных для Вашей предметной области, предоставьте в инструкции определения полей, чтобы модель точно знала, что следует считать сущностью:

prompt_custom = '''
Extract entities from the medical text below using these custom entity types:

Entity Types:
- MEDICATION: Any drug name, trade name, or generic name
- DOSAGE: Amounts and frequencies (mg, mcg, units/day)
- CONDITION: Diagnoses, symptoms, or medical conditions
- PROCEDURE: Medical tests, surgeries, or treatments
- PROVIDER: Doctor names and medical professionals

Return JSON: {"entities": [{"text": str, "type": str}]}

Text: Dr. Patel prescribed Metformin 500mg twice daily for Type 2 Diabetes.
A follow-up HbA1c test is scheduled for next month.
'''

print(prompt_custom)

Пакетное извлечение сущностей

При обработке нескольких документов пакетное извлечение эффективнее. Составьте инструкцию так, чтобы она обрабатывала несколько входных данных и возвращала структурированный результат для каждого документа:

def batch_extract(documents):
    docs_formatted = '\n'.join(
        f'<document id="{i+1}">\n{doc}\n</document>'
        for i, doc in enumerate(documents)
    )

    prompt = f'''
Extract named entities from each document below.
Return JSON: {{
  "results": [
    {{"doc_id": int, "entities": {{"people": [], "organizations": [], "dates": []}}}}
  ]
}}

{docs_formatted}
'''

    r = client.messages.create(
        model='claude-opus-4-5', max_tokens=1000,
        messages=[{'role': 'user', 'content': prompt}]
    )
    return json.loads(r.content[0].text)

docs = [
    'Satya Nadella presented at Microsoft Build 2025.',
    'The WHO released guidelines on May 10.'
]
print(batch_extract(docs))

Постобработка извлечённых сущностей

Перед использованием извлечённые сущности часто требуют постобработки:

from datetime import datetime

def normalize_entities(raw_entities):
    normalized = {'people': [], 'organizations': [], 'dates': [], 'money': []}

    for person in raw_entities.get('people', []):
        normalized['people'].append(person.strip().title())

    for org in raw_entities.get('organizations', []):
        normalized['organizations'].append(org.strip())

    for date_str in raw_entities.get('dates', []):
        # Try to parse to ISO format
        for fmt in ['%B %d, %Y', '%Y-%m-%d', '%b %d, %Y']:
            try:
                parsed = datetime.strptime(date_str.strip(), fmt)
                normalized['dates'].append(parsed.strftime('%Y-%m-%d'))
                break
            except ValueError:
                pass
        else:
            normalized['dates'].append(date_str.strip())

    return normalized

raw = {'people': ['tim cook', 'URSULA VON DER LEYEN'], 'dates': ['March 15, 2025']}
print(normalize_entities(raw))

Оценка качества извлечения

Качество NER измеряется с помощью точности, полноты и показателя F1 на размеченном наборе тестов:

  • Точность: какая доля всех извлечённых сущностей является правильной?
  • Полнота: какая доля всех истинных сущностей была извлечена?
  • F1: гармоническое среднее точности и полноты
def evaluate_extraction(predicted, ground_truth):
    pred_set = set(predicted)
    true_set = set(ground_truth)

    true_positives = len(pred_set & true_set)
    false_positives = len(pred_set - true_set)
    false_negatives = len(true_set - pred_set)

    precision = true_positives / (true_positives + false_positives) if pred_set else 0
    recall = true_positives / (true_positives + false_negatives) if true_set else 0
    f1 = 2 * precision * recall / (precision + recall) if (precision + recall) else 0

    return {'precision': round(precision, 3), 'recall': round(recall, 3), 'f1': round(f1, 3)}

predicted = ['Tim Cook', 'Apple', 'Brussels', 'March 15 2025']
ground_truth = ['Tim Cook', 'Apple', 'Ursula von der Leyen', 'Brussels', 'March 15, 2025', 'European Commission']
print(evaluate_extraction(predicted, ground_truth))

Снижение числа выдуманных сущностей

Иногда модели извлекают сущности, которых нет в исходном тексте, — это галлюцинации. Стратегии их сокращения:

  • Укажите: Извлекайте только сущности, явно упомянутые в тексте. Не делайте выводов и не добавляйте отсутствующие сущности.
  • Укажите: Для каждой сущности приводите точную цитату из текста, в которой она встречается.
  • Выполните постобработку: проверьте, что каждая извлечённая строка сущности действительно встречается в исходном тексте
def anti_hallucination_extract(text):
    prompt = f'''
Extract ONLY entities that are explicitly present in the text below.
Do NOT infer, add, or supplement with external knowledge.
For each entity, include the exact quote from the text.

Return JSON: {{"entities": [{{"text": str, "type": str, "quote": str}}]}}

Text: {text}
'''
    r = client.messages.create(model='claude-opus-4-5', max_tokens=400, messages=[{'role': 'user', 'content': prompt}])
    extracted = json.loads(r.content[0].text)

    # Post-process: verify each entity appears in original text
    verified = [e for e in extracted['entities'] if e['text'].lower() in text.lower()]
    return {'entities': verified}

result = anti_hallucination_extract('Google announced a $5B investment in AI infrastructure.')
print(result)

Разрешение кореференции и связывание сущностей

После извлечения исходных строк сущностей две дополнительные задачи повышают полезность результата на последующих этапах:

  • Разрешение кореференции: связывание слов он, компания и она с именованной сущностью, к которой они относятся
  • Связывание сущностей: сопоставление извлечённых имён с каноническими идентификаторами (например, «Apple» → apple_inc в базе знаний)

Обе задачи можно выполнять с помощью дополнительного шага инструкции после первоначального извлечения.

coref_prompt = '''
Resolve coreferences in the text below.
For each pronoun or definite reference (he, she, it, the company, the CEO),
identify which named entity it refers to.

Return JSON: {"coreferences": [{"text": str, "refers_to": str, "position": int}]}

Text: Apple released its new chip. The company said it would ship in Q4.
Tim Cook announced that he would present it at the fall event.
'''

print(coref_prompt)

Быстрая проверка

Как лучше всего предотвратить извлечение моделью сущностей, отсутствующих в исходном тексте?

Извлечение именованных сущностей — основные выводы

Извлечение именованных сущностей с помощью LLM отличается гибкостью и эффективностью, если инструкция хорошо составлена:

  • Явно определяйте типы сущностей — PERSON, ORG, DATE, LOCATION, MONEY и типы, специфичные для предметной области
  • Используйте в инструкции схему JSON, чтобы обеспечить единообразную структуру выходных данных
  • Добавляйте определения полей для пользовательских типов сущностей, чтобы модель точно знала, что им соответствует
  • Требуйте приводить цитаты из исходного текста, чтобы предотвращать галлюцинации сущностей
  • Выполняйте постобработку для нормализации форматов сущностей (даты приводите к ISO, имена — к регистру заголовка)
  • Оценивайте качество по точности, полноте и показателю F1 на размеченном наборе тестов
  • Для пакетов обрабатывайте несколько документов за один вызов со структурированным результатом для каждого документа

Часто задаваемые вопросы

Урок «Запросы для извлечения именованных сущностей» бесплатный?

Да — полный текст урока «Запросы для извлечения именованных сущностей» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс AI Prompt Engineering, подпишись на CoddyKit PRO. Курс AI Prompt Engineering содержит 4 уроков всего.

Чему я научусь в уроке «Запросы для извлечения именованных сущностей»?

Извлекайте имена, даты, местоположения и пользовательские сущности из неструктурированного текста Ты практикуешь AI Prompt Engineering с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать AI Prompt Engineering?

Предыдущий опыт не требуется. AI Prompt Engineering на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Запросы для извлечения именованных сущностей»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке AI Prompt Engineering?

Да. Каждый урок AI Prompt Engineering включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Запросы для извлечения именованных сущностей
  2. Извлечение данных по схеме
  3. LLM в роли классификатора текста
  4. Уверенность и неопределённость при классификации
← Назад к AI Prompt Engineering