Wyodrębnianie uporządkowanych danych za pomocą wywołań funkcji

Wyświetl w AI od Google Wypróbuj notatnik Colab Wyświetl notatnik na GitHubie

W tym samouczku pokażemy Ci, jak za pomocą interfejsu Gemini API wyodrębniać listy postaci, relacji, rzeczy i miejsc z artykułu.

Konfiguracja

pip install -U -q google-generativeai
import pathlib
import textwrap

import google.generativeai as genai


from IPython.display import display
from IPython.display import Markdown

from google.api_core import retry

def to_markdown(text):
  text = text.replace('•', '  *')
  return Markdown(textwrap.indent(text, '> ', predicate=lambda _: True))

Po uzyskaniu klucza interfejsu API przekaż go do pakietu SDK. Można to zrobić na dwa sposoby:

  • Umieść ten klucz w zmiennej środowiskowej GOOGLE_API_KEY (pakiet SDK automatycznie go stamtąd pobierze).
  • Przekaż klucz urządzeniu genai.configure(api_key=...)
genai.configure(api_key=GOOGLE_API_KEY)

Przykładowe zadanie

W tym samouczku wyodrębnisz encje z artykułów w języku naturalnym. Jako przykładem jest artykuł napisany przez Gemini.

new_story = False

if new_story:
  model = genai.GenerativeModel(model_name='models/gemini-1.5-pro-latest')

  response = model.generate_content("""
      Write a long story about a girl with magic backpack, her family, and at
      least one other charater. Make sure everyone has names. Don't forget to
      describe the contents of the backpack, and where everyone and everything
      starts and ends up.""", request_options={'retry': retry.Retry()})
  story = response.text
  print(response.candidates[0].citation_metadata)
else:
  story = """In the quaint town of Willow Creek, nestled amidst rolling hills and whispering willows, resided a young girl named Anya. As she stepped out of the creaky wooden door of her modest cottage, her heart skipped a beat with excitement and anticipation. Today was her first day of school, and she couldn't wait to show off her prized possession - a magical backpack.\n\nHanded down to her from her grandmother, the backpack was no ordinary satchel. Its soft, emerald-green fabric shimmered with an ethereal glow, and its leather straps held secrets that only Anya knew. Within its capacious interior lay an enchanted world, filled with wonders that would ignite her imagination and change her life forever.\n\nAnya's parents, kind-hearted Elise and wise-bearded Edward, bid her farewell with warm embraces. "Remember, my dear," whispered her mother, "use your magic wisely and for good." Her father added, "Always seek knowledge, and let the backpack be your trusted companion."\n\nWith a skip in her step, Anya set off towards the town's only schoolhouse. On her way, she passed her best friend, Samuel, a curious and adventurous boy with a mischievous grin. "Hey, Anya," he called out. "Can I see your backpack?"\n\nAnya hesitated for a moment before unzipping the flap and revealing its contents. Samuel's eyes widened in amazement as he peered inside. There, nestled amidst pencils and notebooks, were a shimmering sword, a book of ancient spells, a tiny compass that always pointed north, and a magical key that could open any lock.\n\nTogether, they marveled at the backpack's wonders, promising to keep its secrets safe. As they approached the schoolhouse, Anya noticed a group of older children huddled together, their faces etched with fear. Curiosity getting the better of her, she cautiously approached.\n\n"What's wrong?" she asked.\n\nA tall, lanky boy stepped forward. "There's a monster in the forest," he stammered. "It's been terrorizing the town, attacking animals and even people."\n\nAnya's heart sank. The town of Willow Creek was small and peaceful, and the thought of a monster brought a shiver down her spine. She knew she had to do something to protect her family and friends.\n\nWithout a moment's hesitation, Anya opened her backpack and retrieved the shimmering sword. With a determined gleam in her eye, she turned to her terrified peers. "Don't worry," she said, her voice steady. "I'll take care of it."\n\nWith Samuel close behind her, Anya ventured into the shadowy depths of the forest. The trees seemed to whisper secrets as she passed, and the undergrowth rustled with unseen creatures. As they walked deeper into the forest, the air grew heavy and the ground beneath their feet trembled.\n\nSuddenly, they came to a clearing, and there before their eyes was the monster - a massive beast with sharp teeth, glowing red eyes, and claws that could crush a human with ease. The creature roared, a thunderous sound that shook the forest to its core.\n\nFear surged through Anya, but she refused to let it consume her. She drew the sword from its sheath and charged towards the monster. The blade shimmered in the sunlight, and as it struck the beast's hide, a blinding light erupted, enveloping everything in its radiance.\n\nWhen the light faded, the monster was gone, and in its place was a pile of shattered crystals. Anya had defeated the creature with the magic of her backpack, proving that even the smallest of objects could hold the greatest of powers.\n\nAs she and Samuel returned to the town, they were greeted as heroes. The people of Willow Creek rejoiced, and the legend of Anya, the girl with the magic backpack, was passed down through generations. And so, Anya continued her adventures, using the backpack's wonders to make the world a better place, one magical step at a time."""
to_markdown(story)

W urokliwym miasteczku Willow Creek, pośród falistych wzgórz i szeptanych wierzb, mieszkała mała dziewczynka o imieniu Anya. Gdy wyszła spod trzęsących się drewnianych drzwi w skromnym domku, jej serce zatrzęsło z radości i niecierpliwości. Dziś była jej pierwszy dzień w szkole i nie mogła się doczekać, by pochwalić się swoim cennym wyposażeniem – magicznym plecakiem.

Przekazywany jej od babci – plecak nie był zwykłym torbą. Miękki, szmaragdowo-zielony materiał lśnił nieziemską poświatą, a skórzane paski skrywały tajemnice, które znała tylko Ani. W przestronnym wnętrzu krył się zaczarowany świat pełen cudów, które rozpaliłyby jej wyobraźnię i na zawsze odmieniły jej życie.

Rodzice Alicji, życzliwej Elise i mądrze brody Edward, żegnają się z nią w ciepłych uściskach. „Pamiętaj, kochanie” szepcze jej matka: „Używaj magii rozsądnie i w dobrej wierze”. Jej tata dodał: „Zawsze szukaj wiedzy i niech plecak zostanie Twoim zaufanym towarzyszem”.

Z pominięciem kroku ruszyła w stronę jedynej szkoły w mieście. Po drodze spotkała swojego najlepszego przyjaciela Samuela, chłopca ciekawskiego i pełnego przygód chłopca ze psotnym uśmiechem. „Cześć, Ania”, – zawołał. „Widzę twój plecak?”

Wszyscy zawahali się przez chwilę, zanim otwarto klapkę i odkryła zawartość. Gdy Samuel zajrzał do środka, jego oczy rozszerzyły się ze zdziwienia. Wśród ołówków i notatników znajdowały się lśniący miecz, księga starożytnych zaklęć, mały kompas, który zawsze wskazuje północ, oraz magiczny klucz, który otwierał każdy zamek.

Razem zachwycali się cudami plecaka i obiecali, że będą dbać o jego tajemnice. Gdy zbliżyły się do szkoły, Ania zauważyła tłum starszych dzieci, a ich twarze wydrążone ze strachu. Podeszła ostrożnie, aby zacząć rozumieć, co u niej robi.

„Co się stało?” spytała.

Wysoki, chudy chłopiec pojawił się przed siebie. „W lesie jest potwór”, – zaparzał. „Miasto terroryzuje miasto, atakuje zwierzęta, a nawet ludzi”.

Alicja załamała się. Miasto Willow Creek było małe i spokojne, a myśl o potworze sprawiła, że na grzbiecie ciarki drążył dreszczyk emocji. Wiedziała, że musi coś zrobić, by chronić rodzinę i znajomych.

Ani przez chwilę się zastanawiając, otworzyła plecak i wzięła lśniący miecz. Z determinacją w oczach odwróciła się do przerażonych rówieśników. „Nie martw się”, – mówiła spokojnie. „Zajmę się tym”.

Gdy Samuel zbliżył się do siebie, Anya zagłębiała się w ciemne głębiny lasu. Drzewa zdawały się szeptać tajemnice, kiedy mijała, a zarośla szepnęła od niewidocznych stworzeń. Gdy wchodzili głębiej w las, powietrze stawało się ciężkie, a podłoga pod ich stopami drżyła.

Nagle dotarły do polany, gdzie przed ich oczami pojawił się potwór – potężna bestia z ostrymi zębami, lśniącymi czerwonymi oczami i szczypcami, które z łatwością zmiażdżyły człowieka. To stworzenie zasypiało, a jego głośny dźwięk wstrząsnął lasem.

Anya ogarnęła strach, ale nie pozwoliła, aby ją pochłonęła. Wyciągnęła miecz z pochwy i ruszyła w stronę potwora. Ostrze migoczeło w słońcu i gdy uderzyło w skórę bestii, zapaliło się osłonięte światło, które otulowało wszystko w promieniu.

Gdy światło zgasło, potwór zniknął, a na jego miejscu pojawił się stos rozbitych kryształów. Anya pokonała stworzenie za pomocą magii swojego plecaka, udowadniając, że nawet najmniejsze przedmioty mogą kryć największe moce.

Gdy ona i Samuel wrócili do miasta, zostali przywitani jako bohaterowie. Mieszkańcy Willow Creek ucieszyły się, a legenda o Alinie, dziewczynie z magicznym plecakiem, przekazywała się z pokolenia na pokolenia legenda. Anya kontynuowała swoje przygody, krok po kroku dzięki tym cudom, które sprawiły, że świat staje się lepszym miejscem.

Używanie języka naturalnego

Duże modele językowe to zaawansowane narzędzia wielozadaniowe. Często wystarczy zapytać Gemini, o co chcesz, i nie wszystko pójdzie.

Gemini API nie ma trybu JSON, dlatego podczas generowania struktur danych w ten sposób należy zwrócić uwagę na kilka kwestii:

  • Czasami analiza się nie uda.
  • Schemat nie może być ściśle egzekwowany.

Rozwiąż te problemy w następnej sekcji. Najpierw wypróbuj prosty prompt w języku naturalnym ze schematem zapisanym w formie tekstu. Ten element nie został zoptymalizowany:

model = genai.GenerativeModel(
    model_name='models/gemini-1.5-pro-latest')

response = model.generate_content(
  textwrap.dedent("""\
    Please return JSON describing the the people, places, things and relationships from this story using the following schema:

    {"people": list[PERSON], "places":list[PLACE], "things":list[THING], "relationships": list[RELATIONSHIP]}

    PERSON = {"name": str, "description": str, "start_place_name": str, "end_place_name": str}
    PLACE = {"name": str, "description": str}
    THING = {"name": str, "description": str, "start_place_name": str, "end_place_name": str}
    RELATIONSHIP = {"person_1_name": str, "person_2_name": str, "relationship": str}

    All fields are required.

    Important: Only return a single piece of valid JSON text.

    Here is the story:

    """) + story,
  generation_config={'response_mime_type':'application/json'}
)
response.text
'{"people": [\n    {\n        "name": "Anya",\n        "description": "A young girl who lives in the town of Willow Creek with her parents, Elise and Edward. She possesses a magical backpack that was handed down to her from her grandmother.",\n        "start_place_name": "Willow Creek",\n        "end_place_name": "Willow Creek"\n    },\n    {\n        "name": "Elise",\n        "description": "Anya\'s kind-hearted mother",\n        "start_place_name": "Willow Creek",\n        "end_place_name": "Willow Creek"\n    },\n    {\n        "name": "Edward",\n        "description": "Anya\'s wise-bearded father",\n        "start_place_name": "Willow Creek",\n        "end_place_name": "Willow Creek"\n    },\n    {\n        "name": "Samuel",\n        "description": "Anya\'s best friend, a curious and adventurous boy with a mischievous grin.",\n        "start_place_name": "Willow Creek",\n        "end_place_name": "Willow Creek"\n    },\n    {\n        "name": "Monster",\n        "description": "A massive beast with sharp teeth, glowing red eyes, and claws that could crush a human with ease.",\n        "start_place_name": "Forest",\n        "end_place_name": "Forest"\n    }\n], "places": [\n    {\n        "name": "Willow Creek",\n        "description": "A quaint town nestled amidst rolling hills and whispering willows."\n    },\n    {\n        "name": "Forest",\n        "description": "A shadowy place with rustling undergrowth and whispering trees."\n    },\n    {\n        "name": "Schoolhouse",\n        "description": "The only school in the town of Willow Creek."\n    },\n    {\n        "name": "Anya\'s home",\n        "description": "A modest cottage with a creaky wooden door."\n    }\n], "things": [\n    {\n        "name": "Magic backpack",\n        "description": "A magical backpack that was handed down to Anya from her grandmother. Its soft, emerald-green fabric shimmered with an ethereal glow, and its leather straps held secrets that only Anya knew.",\n        "start_place_name": "Anya\'s home",\n        "end_place_name": "Forest"\n    },\n    {\n        "name": "Shimmering sword",\n        "description": "A sword that shimmered in the sunlight and could strike with blinding light.",\n        "start_place_name": "Magic backpack",\n        "end_place_name": "Forest"\n    },\n    {\n        "name": "Book of ancient spells",\n        "description": "A book that contained ancient spells.",\n        "start_place_name": "Magic backpack",\n        "end_place_name": "Forest"\n    },\n    {\n        "name": "Tiny compass",\n        "description": "A compass that always pointed north.",\n        "start_place_name": "Magic backpack",\n        "end_place_name": "Forest"\n    },\n    {\n        "name": "Magical key",\n        "description": "A key that could open any lock.",\n        "start_place_name": "Magic backpack",\n        "end_place_name": "Forest"\n    },\n    {\n        "name": "Shattered crystals",\n        "description": "The remains of the monster after it was defeated by Anya\'s magic backpack.",\n        "start_place_name": "Forest",\n        "end_place_name": "Forest"\n    }\n], "relationships": [\n    {\n        "person_1_name": "Anya",\n        "person_2_name": "Elise",\n        "relationship": "mother-daughter"\n    },\n    {\n        "person_1_name": "Anya",\n        "person_2_name": "Edward",\n        "relationship": "father-daughter"\n    },\n    {\n        "person_1_name": "Anya",\n        "person_2_name": "Samuel",\n        "relationship": "best friends"\n    }\n]}'

To zwróciło ciąg znaków w formacie JSON. Spróbuj go przeanalizować:

import json

print(json.dumps(json.loads(response.text), indent=4))
{
    "people": [
        {
            "name": "Anya",
            "description": "A young girl who lives in the town of Willow Creek with her parents, Elise and Edward. She possesses a magical backpack that was handed down to her from her grandmother.",
            "start_place_name": "Willow Creek",
            "end_place_name": "Willow Creek"
        },
        {
            "name": "Elise",
            "description": "Anya's kind-hearted mother",
            "start_place_name": "Willow Creek",
            "end_place_name": "Willow Creek"
        },
        {
            "name": "Edward",
            "description": "Anya's wise-bearded father",
            "start_place_name": "Willow Creek",
            "end_place_name": "Willow Creek"
        },
        {
            "name": "Samuel",
            "description": "Anya's best friend, a curious and adventurous boy with a mischievous grin.",
            "start_place_name": "Willow Creek",
            "end_place_name": "Willow Creek"
        },
        {
            "name": "Monster",
            "description": "A massive beast with sharp teeth, glowing red eyes, and claws that could crush a human with ease.",
            "start_place_name": "Forest",
            "end_place_name": "Forest"
        }
    ],
    "places": [
        {
            "name": "Willow Creek",
            "description": "A quaint town nestled amidst rolling hills and whispering willows."
        },
        {
            "name": "Forest",
            "description": "A shadowy place with rustling undergrowth and whispering trees."
        },
        {
            "name": "Schoolhouse",
            "description": "The only school in the town of Willow Creek."
        },
        {
            "name": "Anya's home",
            "description": "A modest cottage with a creaky wooden door."
        }
    ],
    "things": [
        {
            "name": "Magic backpack",
            "description": "A magical backpack that was handed down to Anya from her grandmother. Its soft, emerald-green fabric shimmered with an ethereal glow, and its leather straps held secrets that only Anya knew.",
            "start_place_name": "Anya's home",
            "end_place_name": "Forest"
        },
        {
            "name": "Shimmering sword",
            "description": "A sword that shimmered in the sunlight and could strike with blinding light.",
            "start_place_name": "Magic backpack",
            "end_place_name": "Forest"
        },
        {
            "name": "Book of ancient spells",
            "description": "A book that contained ancient spells.",
            "start_place_name": "Magic backpack",
            "end_place_name": "Forest"
        },
        {
            "name": "Tiny compass",
            "description": "A compass that always pointed north.",
            "start_place_name": "Magic backpack",
            "end_place_name": "Forest"
        },
        {
            "name": "Magical key",
            "description": "A key that could open any lock.",
            "start_place_name": "Magic backpack",
            "end_place_name": "Forest"
        },
        {
            "name": "Shattered crystals",
            "description": "The remains of the monster after it was defeated by Anya's magic backpack.",
            "start_place_name": "Forest",
            "end_place_name": "Forest"
        }
    ],
    "relationships": [
        {
            "person_1_name": "Anya",
            "person_2_name": "Elise",
            "relationship": "mother-daughter"
        },
        {
            "person_1_name": "Anya",
            "person_2_name": "Edward",
            "relationship": "father-daughter"
        },
        {
            "person_1_name": "Anya",
            "person_2_name": "Samuel",
            "relationship": "best friends"
        }
    ]
}

To stosunkowo proste rozwiązanie, które często się sprawdza, ale potencjalnie bardziej rygorystyczne lub bardziej niezawodne jest zdefiniowanie schematu za pomocą funkcji wywoływania funkcji interfejsu API.

Użyj wywołań funkcji

Jeśli nie znasz jeszcze samouczka podstaw wywoływania funkcji, zrób to w pierwszej kolejności.

Gdy funkcja wywołuje Twoją funkcję i jej parametry są opisane w interfejsie API jako genai.protos.FunctionDeclaration. W podstawowych przypadkach pakiet SDK może tworzyć FunctionDeclaration z funkcji i jej adnotacji. No więc musisz je teraz zdefiniować.

Zdefiniuj schemat

Zacznij od zdefiniowania person jako obiektu z polami ciągu znaków name, description, start_place_name i end_place_name.

person = genai.protos.Schema(
    type = genai.protos.Type.OBJECT,
    properties = {
        'name':  genai.protos.Schema(type=genai.protos.Type.STRING),
        'description':  genai.protos.Schema(type=genai.protos.Type.STRING),
        'start_place_name': genai.protos.Schema(type=genai.protos.Type.STRING),
        'end_place_name': genai.protos.Schema(type=genai.protos.Type.STRING)
    },
    required=['name', 'description', 'start_place_name', 'end_place_name']
)

Następnie zdefiniuj osoby jako ARRAY z person obiektów:

people = genai.protos.Schema(
    type=genai.protos.Type.ARRAY,
    items=person
)

Zrób to samo w przypadku wszystkich encji, które chcesz wyodrębnić:

place = genai.protos.Schema(
    type = genai.protos.Type.OBJECT,
    properties = {
        'name':  genai.protos.Schema(type=genai.protos.Type.STRING),
        'description':  genai.protos.Schema(type=genai.protos.Type.STRING),
    }
)

places = genai.protos.Schema(
    type=genai.protos.Type.ARRAY,
    items=place
)
thing = genai.protos.Schema(
  type = genai.protos.Type.OBJECT,
  properties = {
      'name':  genai.protos.Schema(type=genai.protos.Type.STRING),
      'description':  genai.protos.Schema(type=genai.protos.Type.STRING),
  }
)

things = genai.protos.Schema(
    type=genai.protos.Type.ARRAY,
    items=thing
)
relationship = genai.protos.Schema(
    type = genai.protos.Type.OBJECT,
    properties = {
        'person_1_name':  genai.protos.Schema(type=genai.protos.Type.STRING),
        'person_2_name':  genai.protos.Schema(type=genai.protos.Type.STRING),
        'relationship':  genai.protos.Schema(type=genai.protos.Type.STRING),
    }
)

relationships = genai.protos.Schema(
    type=genai.protos.Type.ARRAY,
    items=relationship
)

Teraz utwórz FunctionDeclaration:

add_to_database = genai.protos.FunctionDeclaration(
    name="add_to_database",
    description=textwrap.dedent("""\
        Adds entities to the database.
        """),
    parameters=genai.protos.Schema(
        type=genai.protos.Type.OBJECT,
        properties = {
            'people': people,
            'places': places,
            'things': things,
            'relationships': relationships
        }
    )
)

Wywoływanie interfejsu API

Tak jak w podstawowych informacjach o wywoływaniu funkcji możesz teraz przekazać tę wartość FunctionDeclaration do argumentu tools konstruktora genai.GenerativeModel (konstruktor przyjmuje również równoważną reprezentację deklaracji funkcji w formacie JSON):

model = genai.GenerativeModel(
    model_name='models/gemini-1.5-pro-latest',
    tools = [add_to_database])

Za każdym razem, gdy wywołujesz interfejs API, pakiet SDK wysyła narzędzia wraz z promptem, a model powinien wywoływać tę zdefiniowaną przez Ciebie funkcję:

result = model.generate_content(f"""
Please add the people, places, things, and relationships from this story to the database:

{story}
""",
# Force a function call
tool_config={'function_calling_config':'ANY'})

Teraz nie ma tekstu do przeanalizowania. Wynikem tego jest struktura danych.

'text' in result.candidates[0].content.parts[0]
False
'function_call' in result.candidates[0].content.parts[0]
True
fc = result.candidates[0].content.parts[0].function_call
print(type(fc))
<class 'google.ai.generativelanguage_v1beta.types.content.FunctionCall'>

Klasa genai.protos.FunctionCall jest oparta na buforach protokołów Google, przekonwertuj go na bardziej znany obiekt zgodny z JSON:

print(json.dumps(type(fc).to_dict(fc), indent=4))
{
    "name": "add_to_database",
    "args": {
        "things": [
            {
                "name": "Magical Backpack",
                "description": "Anya's prized possession, the Magical Backpack, is no ordinary satchel. Its soft, emerald-green fabric shimmers with an ethereal glow, and its leather straps have secrets that only Anya knows. Within its capacious interior lay an enchanted world, filled with wonders that would ignite her imagination and change her life forever."
            },
            {
                "name": "Shimmering Sword",
                "description": "Among the wonders in Anya's Magical Backpack, lies a shimmering sword. With a determined gleam in her eye, she retrieved the shimmering sword and charged towards the monster."
            },
            {
                "description": "Residing within the Magical Backpack, the Book of Ancient Spells holds secrets untold.",
                "name": "Book of Ancient Spells"
            },
            {
                "description": "Tucked away in the Magical Backpack is a tiny compass that always points north.",
                "name": "Tiny Compass that Always Points North"
            },
            {
                "description": "Hidden within the Magical Backpack is a magical key that can open any lock.",
                "name": "Magical Key that Can Open Any Lock"
            }
        ],
        "relationships": [
            {
                "relationship": "Mother-Daughter",
                "person_1_name": "Anya",
                "person_2_name": "Elise"
            },
            {
                "person_2_name": "Edward",
                "relationship": "Father-Daughter",
                "person_1_name": "Anya"
            },
            {
                "person_2_name": "Samuel",
                "person_1_name": "Anya",
                "relationship": "Best Friends"
            }
        ],
        "people": [
            {
                "name": "Anya",
                "description": "Anya, the main character of the story, is a young girl with a magical backpack.",
                "start_place_name": "Willow Creek",
                "end_place_name": "Unknown"
            },
            {
                "name": "Elise",
                "description": "Anya's mother, Elise is a kind-hearted woman.",
                "end_place_name": "Unknown",
                "start_place_name": "Willow Creek"
            },
            {
                "start_place_name": "Willow Creek",
                "end_place_name": "Unknown",
                "name": "Edward",
                "description": "Anya's father, Edward is a wise-bearded man."
            },
            {
                "end_place_name": "Unknown",
                "start_place_name": "Willow Creek",
                "description": "Anya's best friend, Samuel is a curious and adventurous boy with a mischievous grin.",
                "name": "Samuel"
            }
        ],
        "places": [
            {
                "description": "The quaint town of Willow Creek is nestled amidst rolling hills and whispering willows.",
                "name": "Willow Creek"
            },
            {
                "description": "The town's only schoolhouse.",
                "name": "Schoolhouse"
            },
            {
                "description": "A shadowy place filled with secrets and dangers, the Forest is home to a terrifying monster.",
                "name": "Forest"
            }
        ]
    }
}

Podsumowanie

Interfejs API może rozwiązać problemy z wyodrębnianiem uporządkowanych danych na podstawie danych wejściowych i wyjściowych w postaci samego tekstu, ale wywoływanie funkcji jest bardziej niezawodne, ponieważ pozwala zdefiniować ścisły schemat i eliminuje krok analizy, który może być podatny na błędy.