Afficher sur l'IA de Google | Essayer un notebook Colab | Afficher le notebook sur GitHub |
Dans ce tutoriel, vous allez suivre un exemple d'extraction de données structurées à l'aide de l'API Gemini pour extraire les listes de personnages, de relations, d'éléments et de lieux d'une histoire.
Configuration
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))
Une fois que vous disposez de la clé API, transmettez-la au SDK. Pour cela, vous avez le choix entre deux méthodes :
- Placez la clé dans la variable d'environnement
GOOGLE_API_KEY
(le SDK la récupérera automatiquement à partir de là). - Transmettre la clé à
genai.configure(api_key=...)
genai.configure(api_key=GOOGLE_API_KEY)
Exemple de tâche
Dans ce tutoriel, vous allez extraire des entités à partir d'histoires en langage naturel. Voici un exemple d'article écrit par 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)
Dans la pittoresque ville de Willow Creek, nichée au milieu de collines ondulantes et de saules murmurants, vivait une jeune fille nommée Anya. Lorsqu'elle franchit la porte en bois grinçante de sa modeste maison de campagne, son cœur bat la chamade d'excitation et d'impatience. C'est son premier jour d'école, et elle a hâte de montrer son bien le plus précieux : un sac à dos magique.
Ce sac à dos, qui lui a été transmis par sa grand-mère, n'est pas un simple sac. Son tissu vert émeraude doux scintillait d'une lueur éthérée, et ses bretelles en cuir renfermaient des secrets que seule Anya connaissait. À l'intérieur de ce grand espace se trouvait un monde enchanté, rempli de merveilles qui allaient enflammer son imagination et changer sa vie à jamais.
Les parents d'Anya, la douce Elise et le sage Edward à la barbe fournie, lui font leurs adieux avec de chaleureuses étreintes. "N'oublie pas, ma chérie, lui murmura sa mère, utilise ta magie avec sagesse et pour le bien." Son père ajouta : "Cherche toujours à acquérir des connaissances et laisse le sac à dos être ton compagnon de confiance."
D'un pas léger, Anya se dirige vers l'unique école de la ville. Sur son chemin, elle croise son meilleur ami, Samuel, un garçon curieux et aventureux au sourire malicieux. "Hey, Anya", s'écria-t-il. "Puis-je voir ton sac à dos ?"
Anya hésita un instant avant d'ouvrir la fermeture éclair et de révéler son contenu. Les yeux de Samuel s'écarquillèrent de stupéfaction lorsqu'il regarda à l'intérieur. Au milieu des crayons et des cahiers, se trouvait une épée scintillante, un livre de sorts anciens, une petite boussole qui pointait toujours vers le nord et une clé magique qui pouvait ouvrir n'importe quelle serrure.
Ensemble, ils s'émerveillent des merveilles du sac à dos et promettent de garder ses secrets. En approchant de l'école, Anya a remarqué un groupe d'enfants plus âgés blottis les uns contre les autres, leurs visages marqués par la peur. La curiosité l'emportant, elle s'approche prudemment.
"Qu'est-ce qui ne va pas ?" lui demanda-t-elle.
Un garçon grand et maigre s'avança. "Il y a un monstre dans la forêt", bégaya-t-il. "Il terrorise la ville, attaque des animaux et même des personnes."
Le cœur d'Anya se serra. La ville de Willow Creek est petite et paisible, et l'idée d'un monstre lui donne la chair de poule. Elle savait qu'elle devait faire quelque chose pour protéger sa famille et ses amis.
Sans hésiter, Anya ouvrit son sac à dos et en sortit l'épée scintillante. Avec un regard déterminé, elle se tourne vers ses camarades terrifiés. "Ne vous inquiétez pas", dit-elle d'une voix assurée. "Je m'en occupe."
Samuel la suivant de près, Anya s'aventura dans les profondeurs ténébreuses de la forêt. Les arbres semblaient lui murmurer des secrets tandis qu'elle passait, et les sous-bois bruissaient de créatures invisibles. À mesure qu'ils s'enfonçaient dans la forêt, l'air devenait lourd et le sol tremblait sous leurs pieds.
Soudain, ils arrivent dans une clairière et le monstre se dresse devant eux : une bête immense aux dents acérées, aux yeux rouges brillants et aux griffes capables d'écraser un humain avec facilité. La créature rugit, un bruit tonitruant qui ébranle la forêt jusqu'à ses racines.
La peur l'envahit, mais elle refusa de la laisser la consumer. Elle a sorti l'épée de son fourreau et s'est jetée sur le monstre. La lame scintillait au soleil, et lorsqu'elle a touché la peau de la bête, une lumière aveuglante a éclaté, enveloppant tout dans son rayonnement.
Lorsque la lumière s'est éteinte, le monstre avait disparu, et à sa place se trouvait une pile de cristaux brisés. Anya avait vaincu la créature grâce à la magie de son sac à dos, prouvant que même les plus petits objets pouvaient détenir les plus grands pouvoirs.
Lorsqu'elle et Samuel sont rentrés en ville, ils ont été accueillis en héros. Les habitants de Willow Creek se réjouirent, et la légende d'Anya, la fille au sac à dos magique, fut transmise de génération en génération. Anya poursuivit donc ses aventures, utilisant les merveilles de son sac à dos pour rendre le monde meilleur, une étape magique après l'autre.
Utiliser un langage naturel
Les grands modèles de langage sont des outils multitâches puissants. Souvent, il vous suffit de demander à Gemini ce que vous voulez, et il s'en chargera.
L'API Gemini ne dispose pas de mode JSON. Vous devez donc prendre en compte quelques points lorsque vous générez des structures de données de cette manière:
- Il arrive que l'analyse échoue.
- Le schéma ne peut pas être appliqué de manière stricte.
Vous allez résoudre ces problèmes dans la section suivante. Commencez par essayer une requête simple en langage naturel avec le schéma écrit sous forme de texte. Cette fonctionnalité n'a pas été optimisée:
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]}'
Cela a renvoyé une chaîne JSON. Essayez de l'analyser:
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" } ] }
Cette méthode est relativement simple et fonctionne souvent, mais vous pouvez la rendre plus stricte/robuste en définissant le schéma à l'aide de la fonctionnalité d'appel de fonction de l'API.
Utiliser l'appel de fonction
Si vous n'avez pas encore suivi le tutoriel sur les principes de base des appels de fonction, assurez-vous de le faire en premier.
Avec l'appel de fonction, votre fonction et ses paramètres sont décrits à l'API en tant que genai.protos.FunctionDeclaration
. Dans les cas de base, le SDK peut créer le FunctionDeclaration
à partir de la fonction et de ses annotations. Vous devrez donc les définir explicitement pour le moment.
Définir le schéma
Commencez par définir person
comme un objet avec les champs de chaîne name
, description
, start_place_name
et 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']
)
Définissez ensuite les personnes en tant qu'ARRAY
d'objets person
:
people = genai.protos.Schema(
type=genai.protos.Type.ARRAY,
items=person
)
Faites de même pour chacune des entités que vous essayez d'extraire:
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
)
Créez maintenant le 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
}
)
)
Appeler l'API
Comme vous l'avez vu dans la section Principes de base des appels de fonction, vous pouvez maintenant transmettre ce FunctionDeclaration
à l'argument tools
du constructeur genai.GenerativeModel
(le constructeur accepte également une représentation JSON équivalente de la déclaration de fonction):
model = genai.GenerativeModel(
model_name='models/gemini-1.5-pro-latest',
tools = [add_to_database])
Chaque fois que vous appelez l'API, le SDK envoie les outils avec votre requête, et le modèle doit appeler la fonction que vous avez définie:
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'})
Il n'y a plus de texte à analyser. Le résultat est une structure de données.
'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'>
La classe genai.protos.FunctionCall
est basée sur les tampons de protocole Google. Convertissez-la en objet compatible JSON plus familier:
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" } ] } }
Conclusion
Bien que l'API puisse gérer les problèmes d'extraction de données structurées avec une entrée et une sortie textuelles pures, l'utilisation d'un appel de fonction est probablement plus fiable, car elle vous permet de définir un schéma strict et élimine une étape d'analyse potentiellement sujette à des erreurs.