ट्यूटोरियल: Gemini API की मदद से फ़ंक्शन कॉल करना


ai.google.dev पर देखें Google Colab में चलाएं GitHub पर सोर्स देखें

कस्टम फ़ंक्शन तय करने और उन्हें Gemini पर पास करने के लिए, फ़ंक्शन कॉलिंग का इस्तेमाल करें. मॉडल सीधे तौर पर इन फ़ंक्शन को शुरू नहीं करता है. इसके बजाय, वह स्ट्रक्चर्ड डेटा आउटपुट जनरेट करता है जो फ़ंक्शन के नाम और सुझाए गए तर्कों की जानकारी देता है. यह आउटपुट, बाहरी एपीआई को कॉल करने की सुविधा देता है. साथ ही, एपीआई से मिले आउटपुट को मॉडल में फिर से शामिल किया जा सकता है, ताकि क्वेरी के बेहतर जवाब मिल सकें. फ़ंक्शन कॉलिंग, एलएलएम को रीयल-टाइम की जानकारी के साथ कई सेवाओं, जैसे कि डेटाबेस, कस्टमर रिलेशनशिप मैनेजमेंट सिस्टम, और दस्तावेज़ का डेटा स्टोर करने की जगह से इंटरैक्ट करने की सुविधा देता है. इससे काम के और कॉन्टेक्स्ट के हिसाब से जवाब देने की उनकी क्षमता बेहतर होती है. Gemini मॉडल को फ़ंक्शन की जानकारी दी जा सकती है. आपकी क्वेरी को हैंडल करने में मॉडल की मदद करने के लिए, मॉडल आपसे किसी फ़ंक्शन को कॉल करने और नतीजा वापस भेजने के लिए कह सकता है.

अगर आपने अब तक ऐसा नहीं किया है, तो ज़्यादा जानने के लिए फ़ंक्शन कॉलिंग के बारे में जानकारी देखें.

सेटअप

Python SDK टूल इंस्टॉल करें

Gemini API के लिए Python SDK टूल, google-generativeai पैकेज में शामिल होता है. पीआईपी (पिक्चर में पिक्चर) का इस्तेमाल करके डिपेंडेंसी इंस्टॉल करें:

pip install -U -q google-generativeai

पैकेज इंपोर्ट करें

ज़रूरी पैकेज इंपोर्ट करें.

import pathlib
import textwrap
import time

import google.generativeai as genai

from IPython import display
from IPython.display import Markdown

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

अपनी एपीआई कुंजी सेट अप करें

Gemini API का इस्तेमाल करने से पहले, आपको एपीआई पासकोड हासिल करना होगा. अगर आपके पास पहले से कोई कुंजी नहीं है, तो Google AI Studio में सिर्फ़ एक क्लिक करके कुंजी बनाएं.

एपीआई पासकोड पाएं

Colab में, सीक्रेट मैनेजर में बाईं ओर मौजूद पैनल में " दिलचस्पी" में जाकर कुंजी जोड़ें. इसे API_KEY नाम दें.

एपीआई पासकोड मिलने के बाद, उसे SDK टूल को पास करें. आप इसे दो तरीकों से कर सकते हैं:

  • कुंजी को GOOGLE_API_KEY के एनवायरमेंट वैरिएबल में डालें. SDK टूल इसे वहां से अपने-आप चुन लेगा.
  • कुंजी को genai.configure(api_key=...) पर पास करें
try:
    # Used to securely store your API key
    from google.colab import userdata

    # Or use `os.getenv('API_KEY')` to fetch an environment variable.
    GOOGLE_API_KEY=userdata.get('GOOGLE_API_KEY')
except ImportError:
    import os
    GOOGLE_API_KEY = os.environ['GOOGLE_API_KEY']

genai.configure(api_key=GOOGLE_API_KEY)

फ़ंक्शन कॉल करने से जुड़ी बुनियादी बातें

फ़ंक्शन कॉलिंग का इस्तेमाल करने के लिए, GenerativeModel बनाते समय, tools पैरामीटर में फ़ंक्शन की एक सूची पास करें. यह मॉडल, फ़ंक्शन का नाम, docstring, पैरामीटर, और पैरामीटर टाइप एनोटेशन का इस्तेमाल करके, यह तय करता है कि किसी सवाल का सबसे अच्छा जवाब देने के लिए फ़ंक्शन की ज़रूरत है या नहीं.

def multiply(a:float, b:float):
    """returns a * b."""
    return a*b

model = genai.GenerativeModel(model_name='gemini-1.0-pro',
                              tools=[multiply])

model
genai.GenerativeModel(
    model_name='models/gemini-1.0-pro',
    generation_config={},
    safety_settings={},
    tools=<google.generativeai.types.content_types.FunctionLibrary object at 0x10e73fe90>,
)

हमारा सुझाव है कि आप चैट इंटरफ़ेस के ज़रिए फ़ंक्शन कॉल का इस्तेमाल करें. ऐसा इसलिए होता है, क्योंकि फ़ंक्शन कॉल कई बारी वाली चैट में स्वाभाविक रूप से फ़िट हो जाते हैं, क्योंकि ये उपयोगकर्ता और मॉडल के बीच होने वाले बातचीत को कैप्चर करते हैं. Python SDK टूल का ChatSession, चैट के लिए एक बेहतरीन इंटरफ़ेस है. यह आपकी बातचीत के इतिहास को मैनेज करता है. साथ ही, enable_automatic_function_calling पैरामीटर का इस्तेमाल करने से, फ़ंक्शन कॉल करना और भी आसान हो जाता है:

chat = model.start_chat(enable_automatic_function_calling=True)

अपने-आप फ़ंक्शन कॉलिंग की सुविधा चालू होने पर, chat.send_message आपके फ़ंक्शन को अपने-आप कॉल करता है. ऐसा तब होता है, जब मॉडल ऐसा करने के लिए कहता है.

ऐसा लगता है कि सही जवाब के साथ सिर्फ़ टेक्स्ट जवाब दिया गया है:

response = chat.send_message('I have 57 cats, each owns 44 mittens, how many mittens is that in total?')
response.text
'The total number of mittens is 2508.'
57*44
2508

बातचीत का फ़्लो और फ़ंक्शन कॉल किस तरह से इंटिग्रेट किए गए हैं, यह देखने के लिए चैट के इतिहास की जांच करें.

ChatSession.history प्रॉपर्टी में, उपयोगकर्ता और Gemini मॉडल के बीच हुई बातचीत का समय के हिसाब से रिकॉर्ड सेव किया जाता है. बातचीत के हर मोड़ को एक glm.Content ऑब्जेक्ट के तौर पर दिखाया जाता है. इस ऑब्जेक्ट में यह जानकारी होती है:

  • भूमिका: इससे पता चलता है कि कॉन्टेंट "उपयोगकर्ता" से लिया गया है या "मॉडल" से.
  • हिस्से: glm.Part ऑब्जेक्ट की ऐसी सूची जो मैसेज के अलग-अलग कॉम्पोनेंट दिखाती है. सिर्फ़ टेक्स्ट वाले मॉडल में ये हिस्से हो सकते हैं:
    • टेक्स्ट: सादा मैसेज.
    • फ़ंक्शन कॉल (glm.FunctionCall): दिए गए तर्कों के साथ किसी फ़ंक्शन को चलाने के लिए, मॉडल से किया जाने वाला अनुरोध.
    • फ़ंक्शन रिस्पॉन्स (glm.FunctionResponse): अनुरोध किए गए फ़ंक्शन को लागू करने के बाद, उपयोगकर्ता से मिला नतीजा.

पिछले उदाहरण में, दस्ताने की गणना के साथ, इतिहास में यह क्रम दिखाया गया है:

  1. उपयोगकर्ता: दस्ताने की कुल संख्या के बारे में सवाल पूछा जाता है.
  2. मॉडल: इससे पता चलता है कि गुणा करने वाला फ़ंक्शन काम का है या नहीं और उपयोगकर्ता को FunctionCall अनुरोध भेजता है.
  3. उपयोगकर्ता: ChatSession फ़ंक्शन, enable_automatic_function_calling सेट होने की वजह से अपने-आप काम करता है और कैलकुलेट किए गए नतीजे के साथ FunctionResponse भेजता है.
  4. मॉडल: फ़ाइनल जवाब बनाने के लिए, फ़ंक्शन के आउटपुट का इस्तेमाल करता है और उसे टेक्स्ट रिस्पॉन्स के तौर पर दिखाता है.
for content in chat.history:
    part = content.parts[0]
    print(content.role, "->", type(part).to_dict(part))
    print('-'*80)
user -> {'text': 'I have 57 cats, each owns 44 mittens, how many mittens is that in total?'}
--------------------------------------------------------------------------------
model -> {'function_call': {'name': 'multiply', 'args': {'a': 57.0, 'b': 44.0} } }
--------------------------------------------------------------------------------
user -> {'function_response': {'name': 'multiply', 'response': {'result': 2508.0} } }
--------------------------------------------------------------------------------
model -> {'text': 'The total number of mittens is 2508.'}
--------------------------------------------------------------------------------

आम तौर पर, राज्य का डायग्राम यह होता है:

मॉडल कभी भी टेक्स्ट या FunctionCall का जवाब दे सकता है. अगर मॉडल कोई FunctionCall भेजता है, तो उपयोगकर्ता को FunctionResponse से जवाब देना होगा

मॉडल, टेक्स्ट का जवाब देने से पहले कई फ़ंक्शन कॉल का जवाब दे सकता है और फ़ंक्शन कॉल, टेक्स्ट का जवाब देने से पहले आता है.

यह सब अपने-आप मैनेज होता है. अगर आपको ज़्यादा कंट्रोल चाहिए, तो ये काम किए जा सकते हैं:

  • डिफ़ॉल्ट enable_automatic_function_calling=False को छोड़ें और glm.FunctionCall के जवाबों को खुद प्रोसेस करें.
  • आप चाहें, तो GenerativeModel.generate_content का इस्तेमाल करें. इसमें आपको चैट का इतिहास भी मैनेज करना होगा.

पैरलल फ़ंक्शन कॉल करना

ऊपर बताए गए बेसिक फ़ंक्शन कॉलिंग के अलावा, एक ही मोड़ में कई फ़ंक्शन कॉल भी किए जा सकते हैं. इस सेक्शन में, पैरलल फ़ंक्शन कॉलिंग का इस्तेमाल करने का उदाहरण दिया गया है.

टूल तय करें.

def power_disco_ball(power: bool) -> bool:
    """Powers the spinning disco ball."""
    print(f"Disco ball is {'spinning!' if power else 'stopped.'}")
    return True


def start_music(energetic: bool, loud: bool, bpm: int) -> str:
    """Play some music matching the specified parameters.

    Args:
      energetic: Whether the music is energetic or not.
      loud: Whether the music is loud or not.
      bpm: The beats per minute of the music.

    Returns: The name of the song being played.
    """
    print(f"Starting music! {energetic=} {loud=}, {bpm=}")
    return "Never gonna give you up."


def dim_lights(brightness: float) -> bool:
    """Dim the lights.

    Args:
      brightness: The brightness of the lights, 0.0 is off, 1.0 is full.
    """
    print(f"Lights are now set to {brightness:.0%}")
    return True

अब मॉडल को ऐसे निर्देश के साथ कॉल करें जो सभी बताए गए टूल का इस्तेमाल कर सके.

# Set the model up with tools.
house_fns = [power_disco_ball, start_music, dim_lights]

model = genai.GenerativeModel(model_name="gemini-1.5-pro-latest", tools=house_fns)

# Call the API.
chat = model.start_chat()
response = chat.send_message("Turn this place into a party!")

# Print out each of the function calls requested from this single call.
for part in response.parts:
    if fn := part.function_call:
        args = ", ".join(f"{key}={val}" for key, val in fn.args.items())
        print(f"{fn.name}({args})")
power_disco_ball(power=True)
start_music(energetic=True, loud=True, bpm=120.0)
dim_lights(brightness=0.3)

प्रिंट किए गए हर नतीजे में, मॉडल से अनुरोध किया गया सिंगल फ़ंक्शन कॉल दिखता है. नतीजों को वापस भेजने के लिए, सभी जवाबों को उसी क्रम में शामिल करें जिस क्रम में उनसे अनुरोध किया गया था.

# Simulate the responses from the specified tools.
responses = {
    "power_disco_ball": True,
    "start_music": "Never gonna give you up.",
    "dim_lights": True,
}

# Build the response parts.
response_parts = [
    glm.Part(function_response=glm.FunctionResponse(name=fn, response={"result": val}))
    for fn, val in responses.items()
]

response = chat.send_message(response_parts)
print(response.text)
Let's get this party started! I've turned on the disco ball, started playing some upbeat music, and dimmed the lights. 🎶✨  Get ready to dance! 🕺💃

(ज़रूरी नहीं) कम लेवल का ऐक्सेस

Python फ़ंक्शन से स्कीमा को अपने-आप निकालने की सुविधा, सभी मामलों में काम नहीं करती. उदाहरण के लिए: यह उन मामलों को हैंडल नहीं करता है जहां आप नेस्ट किए गए डिक्शनरी-ऑब्जेक्ट के फ़ील्ड के बारे में बताते हैं, लेकिन एपीआई इसके साथ काम करता है. एपीआई इनमें से किसी भी तरह के बारे में बता सकता है:

AllowedType = (int | float | bool | str | list['AllowedType'] | dict[str, AllowedType]

google.ai.generativelanguage क्लाइंट लाइब्रेरी की मदद से, लो लेवल वाले उन डेटा टाइप का ऐक्सेस दिया जा सकता है जिन पर आपको पूरा कंट्रोल मिलता है.

import google.ai.generativelanguage as glm

सबसे पहले मॉडल के _tools एट्रिब्यूट के बारे में जानें. यहां देखें कि मॉडल को पास किए गए फ़ंक्शन की जानकारी कैसे दी जाती है:

def multiply(a:float, b:float):
    """returns a * b."""
    return a*b

model = genai.GenerativeModel(model_name='gemini-1.0-pro',
                             tools=[multiply])

model._tools.to_proto()
[function_declarations {
   name: "multiply"
   description: "returns a * b."
   parameters {
     type_: OBJECT
     properties {
       key: "b"
       value {
         type_: NUMBER
       }
     }
     properties {
       key: "a"
       value {
         type_: NUMBER
       }
     }
     required: "a"
     required: "b"
   }
 }]

इससे, glm.Tool ऑब्जेक्ट की सूची मिलती है, जिसे एपीआई को भेजा जाएगा. अगर प्रिंट किए गए फ़ॉर्मैट आपको नहीं पता, तो इसकी वजह यह है कि ये Google प्रोटोबफ़ क्लास हैं. हर glm.Tool (इस मामले में 1) में glm.FunctionDeclarations की एक सूची होती है. यह फ़ंक्शन, उसके आर्ग्युमेंट के बारे में बताती है.

यहां glm क्लास का इस्तेमाल करके, एक ही गुणा करने वाले फ़ंक्शन के लिए एलान किया गया है.

ध्यान दें कि ये क्लास सिर्फ़ एपीआई के फ़ंक्शन के बारे में बताती हैं, उनमें इसे लागू करने की ज़रूरत नहीं है. इसलिए, इसका इस्तेमाल अपने-आप होने वाले फ़ंक्शन कॉल के साथ नहीं किया जा सकता. हालांकि, फ़ंक्शन के लिए हमेशा लागू करने की ज़रूरत नहीं होती.

calculator = glm.Tool(
    function_declarations=[
      glm.FunctionDeclaration(
        name='multiply',
        description="Returns the product of two numbers.",
        parameters=glm.Schema(
            type=glm.Type.OBJECT,
            properties={
                'a':glm.Schema(type=glm.Type.NUMBER),
                'b':glm.Schema(type=glm.Type.NUMBER)
            },
            required=['a','b']
        )
      )
    ])

इसी तरह, इसे JSON के साथ काम करने वाले ऑब्जेक्ट के तौर पर बताया जा सकता है:

calculator = {'function_declarations': [
      {'name': 'multiply',
       'description': 'Returns the product of two numbers.',
       'parameters': {'type_': 'OBJECT',
       'properties': {
         'a': {'type_': 'NUMBER'},
         'b': {'type_': 'NUMBER'} },
       'required': ['a', 'b']} }]}
glm.Tool(calculator)
function_declarations {
  name: "multiply"
  description: "Returns the product of two numbers."
  parameters {
    type_: OBJECT
    properties {
      key: "b"
      value {
        type_: NUMBER
      }
    }
    properties {
      key: "a"
      value {
        type_: NUMBER
      }
    }
    required: "a"
    required: "b"
  }
}

दोनों में से किसी भी तरीके से, आप glm.Tool या टूल की सूची को

model = genai.GenerativeModel('gemini-pro', tools=calculator)
chat = model.start_chat()

response = chat.send_message(
    f"What's 234551 X 325552 ?",
)

ठीक वैसे ही, जब मॉडल कैलकुलेटर के multiply फ़ंक्शन को शुरू करने के लिए glm.FunctionCall का इस्तेमाल करता है:

response.candidates
[index: 0
content {
  parts {
    function_call {
      name: "multiply"
      args {
        fields {
          key: "b"
          value {
            number_value: 325552
          }
        }
        fields {
          key: "a"
          value {
            number_value: 234551
          }
        }
      }
    }
  }
  role: "model"
}
finish_reason: STOP
]

फ़ंक्शन खुद एक्ज़ीक्यूट करें:

fc = response.candidates[0].content.parts[0].function_call
assert fc.name == 'multiply'

result = fc.args['a'] * fc.args['b']
result
76358547152.0

बातचीत जारी रखने के लिए, मॉडल को नतीजा भेजें:

response = chat.send_message(
    glm.Content(
    parts=[glm.Part(
        function_response = glm.FunctionResponse(
          name='multiply',
          response={'result': result}))]))

खास जानकारी

बेसिक फ़ंक्शन कॉलिंग, SDK टूल में काम करती है. याद रखें कि चैट मोड का इस्तेमाल करके इसे आसानी से मैनेज किया जा सकता है, क्योंकि इसमें एक ही तरह की स्वाभाविक संरचना होती है. आपके पास फ़ंक्शन को कॉल करने और मॉडल को नतीजे वापस भेजने की ज़िम्मेदारी होती है, ताकि यह टेक्स्ट-रिस्पॉन्स दे सके.