참고소스 수정본

This commit is contained in:
LASTA_DEV01\lasta
2026-05-12 19:40:31 +09:00
parent 0f34a451fc
commit 2e9204243d
8708 changed files with 3259488 additions and 869 deletions

View File

@@ -0,0 +1,12 @@
from neo4j_graphrag.llm import AnthropicLLM, LLMResponse
# set api key here on in the ANTHROPIC_API_KEY env var
api_key = None
with AnthropicLLM(
model_name="claude-3-opus-20240229",
model_params={"max_tokens": 1000}, # max_tokens must be specified
api_key=api_key,
) as llm:
res: LLMResponse = llm.invoke("say something")
print(res.content)

View File

@@ -0,0 +1,22 @@
from botocore.exceptions import ClientError, NoCredentialsError, PartialCredentialsError
from neo4j_graphrag.llm import BedrockLLM
# AWS credentials are read from environment or ~/.aws/credentials
llm = BedrockLLM(
model_name="us.anthropic.claude-sonnet-4-20250514-v1:0",
model_params={"temperature": 0.7, "maxTokens": 1024},
region_name="us-east-1",
)
try:
res = llm.invoke("say something")
print(res.content)
except NoCredentialsError:
print(
"AWS credentials not found. Run 'aws configure' or set environment variables."
)
except PartialCredentialsError as e:
print(f"Incomplete AWS credentials: {e}")
except ClientError as e:
print(f"AWS API error: {e}")

View File

@@ -0,0 +1,11 @@
from neo4j_graphrag.llm import CohereLLM, LLMResponse
# set api key here on in the CO_API_KEY env var
api_key = None
with CohereLLM(
model_name="command-r",
api_key=api_key,
) as llm:
res: LLMResponse = llm.invoke("say something")
print(res.content)

View File

@@ -0,0 +1,83 @@
import random
import string
from typing import Any, Awaitable, Callable, List, Optional, TypeVar, Union
from neo4j_graphrag.llm import LLMInterface, LLMResponse
from neo4j_graphrag.utils.rate_limit import (
RateLimitHandler,
# rate_limit_handler,
# async_rate_limit_handler,
)
from neo4j_graphrag.message_history import MessageHistory
from neo4j_graphrag.types import LLMMessage
from neo4j_graphrag.exceptions import RetryableError
class CustomLLM(LLMInterface):
def __init__(
self, model_name: str, system_instruction: Optional[str] = None, **kwargs: Any
):
super().__init__(model_name, **kwargs)
# Optional: Apply rate limit handling to synchronous invoke method
# @rate_limit_handler
def invoke(
self,
input: str,
message_history: Optional[Union[List[LLMMessage], MessageHistory]] = None,
system_instruction: Optional[str] = None,
) -> LLMResponse:
content: str = (
self.model_name + ": " + "".join(random.choices(string.ascii_letters, k=30))
)
return LLMResponse(content=content)
# Optional: Apply rate limit handling to asynchronous ainvoke method
# @async_rate_limit_handler
async def ainvoke(
self,
input: str,
message_history: Optional[Union[List[LLMMessage], MessageHistory]] = None,
system_instruction: Optional[str] = None,
) -> LLMResponse:
raise NotImplementedError()
llm = CustomLLM(
""
) # if rate_limit_handler and async_rate_limit_handler decorators are used, the default rate limit handler will be applied automatically (retry with exponential backoff)
res: LLMResponse = llm.invoke("text")
print(res.content)
# If rate_limit_handler and async_rate_limit_handler decorators are used and you want to use a custom rate limit handler
# Type variables for function signatures used in rate limit handlers
F = TypeVar("F", bound=Callable[..., Any])
AF = TypeVar("AF", bound=Callable[..., Awaitable[Any]])
class CustomRateLimitHandler(RateLimitHandler):
def __init__(self) -> None:
super().__init__()
def handle_sync(self, func: F) -> F:
# error handling here
return func
def handle_async(self, func: AF) -> AF:
# error handling here
return func
def is_retryable_exception(self, exception: Exception) -> bool:
# return True if the exception should be retried
return True
def to_retryable_error(self, exception: Exception) -> RetryableError:
# convert the exception to a retryable error
return RetryableError(exception)
llm_with_custom_rate_limit_handler = CustomLLM(
"", rate_limit_handler=CustomRateLimitHandler()
)
result: LLMResponse = llm_with_custom_rate_limit_handler.invoke("text")
print(result.content)

View File

@@ -0,0 +1,31 @@
"""This example illustrates the message_history feature
of the LLMInterface by mocking a conversation between a user
and an LLM about Tom Hanks.
OpenAILLM can be replaced by any supported LLM from this package.
"""
from neo4j_graphrag.llm import LLMResponse, OpenAILLM
# set api key here on in the OPENAI_API_KEY env var
api_key = None
questions = [
"What are some movies Tom Hanks starred in?",
"Is he also a director?",
"Wow, that's impressive. And what about his personal life, does he have children?",
]
history: list[dict[str, str]] = []
with OpenAILLM(model_name="gpt-5", api_key=api_key) as llm:
for question in questions:
res: LLMResponse = llm.invoke(
question,
message_history=history, # type: ignore
)
history.append({"role": "user", "content": question})
history.append({"role": "assistant", "content": res.content})
print("#" * 50, question)
print(res.content)
print("#" * 50)

View File

@@ -0,0 +1,48 @@
"""This example illustrates the message_history feature
of the LLMInterface by mocking a conversation between a user
and an LLM about Tom Hanks.
Neo4j is used as the database for storing the message history.
OpenAILLM can be replaced by any supported LLM from this package.
"""
import neo4j
from neo4j_graphrag.llm import LLMResponse, OpenAILLM
from neo4j_graphrag.message_history import Neo4jMessageHistory
# Define database credentials
URI = "neo4j+s://demo.neo4jlabs.com"
AUTH = ("recommendations", "recommendations")
DATABASE = "recommendations"
INDEX = "moviePlotsEmbedding"
# set api key here on in the OPENAI_API_KEY env var
api_key = None
questions = [
"What are some movies Tom Hanks starred in?",
"Is he also a director?",
"Wow, that's impressive. And what about his personal life, does he have children?",
]
driver = neo4j.GraphDatabase.driver(
URI,
auth=AUTH,
database=DATABASE,
)
history = Neo4jMessageHistory(session_id="123", driver=driver, window=10)
with OpenAILLM(model_name="gpt-5", api_key=api_key) as llm:
for question in questions:
res: LLMResponse = llm.invoke(
question,
message_history=history,
)
history.add_message({"role": "user", "content": question})
history.add_message({"role": "assistant", "content": res.content})
print("#" * 50, question)
print(res.content)
print("#" * 50)

View File

@@ -0,0 +1,18 @@
"""This example illustrates how to set system instructions for LLM.
OpenAILLM can be replaced by any supported LLM from this package.
"""
from neo4j_graphrag.llm import LLMResponse, OpenAILLM
# set api key here on in the OPENAI_API_KEY env var
api_key = None
question = "How fast is Santa Claus during the Christmas eve?"
with OpenAILLM(model_name="gpt-5", api_key=api_key) as llm:
res: LLMResponse = llm.invoke(
question,
system_instruction="Answer with a serious tone",
)
print(res.content)

View File

@@ -0,0 +1,10 @@
from neo4j_graphrag.llm import MistralAILLM
# set api key here on in the MISTRAL_API_KEY env var
api_key = None
with MistralAILLM(
model_name="mistral-small-latest",
api_key=api_key,
) as llm:
llm.invoke("say something")

View File

@@ -0,0 +1,13 @@
"""This example demonstrate how to invoke an LLM using a local model
served by Ollama.
"""
from neo4j_graphrag.llm import LLMResponse, OllamaLLM
with OllamaLLM(
model_name="<model_name>",
# model_params={"options": {"temperature": 0}, "format": "json"},
# host="...", # if using a remote server
) as llm:
res: LLMResponse = llm.invoke("What is the additive color model?")
print(res.content)

View File

@@ -0,0 +1,95 @@
"""
Example showing how to use Ollama tool calls with parameter extraction.
Both synchronous and asynchronous examples are provided.
To run this example:
1. Make sure you have `ollama serve` running
2. Run: python examples/tool_calls/ollama_tool_calls.py
"""
import asyncio
import json
from typing import Dict, Any
from neo4j_graphrag.llm import OllamaLLM
from neo4j_graphrag.llm.types import ToolCallResponse
from neo4j_graphrag.tool import (
Tool,
ObjectParameter,
StringParameter,
IntegerParameter,
)
# Create a custom Tool implementation for person info extraction
parameters = ObjectParameter(
description="Parameters for extracting person information",
properties={
"name": StringParameter(description="The person's full name"),
"age": IntegerParameter(description="The person's age"),
"occupation": StringParameter(description="The person's occupation"),
},
required_properties=["name"],
additional_properties=False,
)
person_info_tool = Tool(
name="extract_person_info",
description="Extract information about a person from text",
parameters=parameters,
execute_func=lambda **kwargs: kwargs,
)
# Create the tool instance
TOOLS = [person_info_tool]
def process_tool_calls(response: ToolCallResponse) -> Dict[str, Any]:
"""Process all tool calls in the response and return the extracted parameters."""
if not response.tool_calls:
raise ValueError("No tool calls found in response")
print(f"\nNumber of tool calls: {len(response.tool_calls)}")
print(f"Additional content: {response.content or 'None'}")
results = []
for i, tool_call in enumerate(response.tool_calls):
print(f"\nTool call #{i + 1}: {tool_call.name}")
print(f"Arguments: {tool_call.arguments}")
results.append(tool_call.arguments)
# For backward compatibility, return the first tool call's arguments
return results[0] if results else {}
async def main() -> None:
async with OllamaLLM(
model_name="mistral:latest", model_params={"options": {"temperature": 0}}
) as llm:
# Example text containing information about a person
text = "Stella Hane is a 35-year-old software engineer who loves coding."
print("\n=== Synchronous Tool Call ===")
# Make a synchronous tool call
sync_response = llm.invoke_with_tools(
input=f"Extract information about the person from this text: {text}",
tools=TOOLS,
)
sync_result = process_tool_calls(sync_response)
print("\n=== Synchronous Tool Call Result ===")
print(json.dumps(sync_result, indent=2))
print("\n=== Asynchronous Tool Call ===")
# Make an asynchronous tool call with a different text
text2 = "Molly Hane, 32, works as a data scientist and enjoys machine learning."
async_response = await llm.ainvoke_with_tools(
input=f"Extract information about the person from this text: {text2}",
tools=TOOLS,
)
async_result = process_tool_calls(async_response)
print("\n=== Asynchronous Tool Call Result ===")
print(json.dumps(async_result, indent=2))
if __name__ == "__main__":
# Run the async main function
asyncio.run(main())

View File

@@ -0,0 +1,8 @@
from neo4j_graphrag.llm import LLMResponse, OpenAILLM
# set api key here on in the OPENAI_API_KEY env var
api_key = None
with OpenAILLM(model_name="gpt-5", api_key=api_key) as llm:
res: LLMResponse = llm.invoke("say something")
print(res.content)

View File

@@ -0,0 +1,122 @@
# Copyright (c) "Neo4j"
# Neo4j Sweden AB [https://neo4j.com]
# #
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# #
# https://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Simple example comparing OpenAI LLM V1 (legacy) vs V2 (structured output).
This demonstrates how V2's structured output provides type-safe, validated responses
compared to V1's prompt-based JSON extraction.
Prerequisites:
- OpenAI API key set in OPENAI_API_KEY environment variable
"""
from dotenv import load_dotenv
from pydantic import BaseModel, ConfigDict
from neo4j_graphrag.llm import OpenAILLM
from neo4j_graphrag.types import LLMMessage
load_dotenv()
# Define a Pydantic model for structured output
class Movie(BaseModel):
model_config = ConfigDict(
extra="forbid"
) # This is important to prevent extra properties from being added to the response
title: str
year: int
director: str
genre: str
# =============================================================================
# V1 (Legacy): Manual JSON mode with prompt engineering
# =============================================================================
print("=" * 60)
print("V1 Legacy: Manual JSON extraction with prompt engineering")
print("=" * 60)
with (
OpenAILLM(
model_name="gpt-5-mini",
model_params={"response_format": {"type": "json_object"}, "temperature": 0},
) as llm_v1,
OpenAILLM(model_name="gpt-5-mini") as llm_v2,
):
# V1 requires string input and explicit JSON instructions in the prompt
v1_prompt = """Extract movie information and respond in JSON format.
Include: title, year, director, genre.
Text: Inception was directed by Christopher Nolan in 2010. It's a science fiction thriller."""
response_v1 = llm_v1.invoke(v1_prompt)
print(f"Response: {response_v1.content}")
# =============================================================================
# V2 (New): Structured output with Pydantic model
# =============================================================================
print("\n" + "=" * 60)
print("V2: Structured output with Pydantic model")
print("=" * 60)
# V2 uses list of LLMMessage for input
messages = [
LLMMessage(
role="user",
content="Inception was directed by Christopher Nolan in 2010. It's a science fiction thriller.",
)
]
# Pass response_format and temperature directly to invoke()
response_v2 = llm_v2.invoke(messages, response_format=Movie, temperature=0)
# Parse and validate in one step
movie = Movie.model_validate_json(response_v2.content)
print(f"Response: {response_v2.content}")
# =============================================================================
# V2: Using JSON Schema instead of Pydantic
# =============================================================================
print("\n" + "=" * 60)
print("V2 Alternative: Structured output with JSON Schema")
print("=" * 60)
# Define a JSON schema (equivalent to the Movie Pydantic model)
# Note: OpenAI requires JSON schemas to be wrapped in this specific format
movie_schema = {
"type": "json_schema",
"json_schema": {
"name": "movie_info",
"schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"year": {"type": "integer"},
"director": {"type": "string"},
"genre": {"type": "string"},
},
"required": ["title", "year", "director", "genre"],
"additionalProperties": False,
},
},
}
# Pass JSON schema as response_format
response_v2_schema = llm_v2.invoke(
messages, response_format=movie_schema, temperature=0
)
print(f"Response: {response_v2_schema.content}")

View File

@@ -0,0 +1,104 @@
"""
Example showing how to use OpenAI tool calls with parameter extraction.
Both synchronous and asynchronous examples are provided.
To run this example:
1. Make sure you have the OpenAI API key in your .env file:
OPENAI_API_KEY=your-api-key
2. Run: python examples/tool_calls/openai_tool_calls.py
"""
import asyncio
import json
import os
from typing import Dict, Any
from dotenv import load_dotenv
from neo4j_graphrag.llm import OpenAILLM
from neo4j_graphrag.llm.types import ToolCallResponse
from neo4j_graphrag.tool import (
Tool,
ObjectParameter,
StringParameter,
IntegerParameter,
)
# Load environment variables from .env file (OPENAI_API_KEY required for this example)
load_dotenv()
# Create a custom Tool implementation for person info extraction
parameters = ObjectParameter(
description="Parameters for extracting person information",
properties={
"name": StringParameter(description="The person's full name"),
"age": IntegerParameter(description="The person's age"),
"occupation": StringParameter(description="The person's occupation"),
},
required_properties=["name"],
additional_properties=False,
)
person_info_tool = Tool(
name="extract_person_info",
description="Extract information about a person from text",
parameters=parameters,
execute_func=lambda **kwargs: kwargs,
)
# Create the tool instance
TOOLS = [person_info_tool]
def process_tool_calls(response: ToolCallResponse) -> Dict[str, Any]:
"""Process all tool calls in the response and return the extracted parameters."""
if not response.tool_calls:
raise ValueError("No tool calls found in response")
print(f"\nNumber of tool calls: {len(response.tool_calls)}")
print(f"Additional content: {response.content or 'None'}")
results = []
for i, tool_call in enumerate(response.tool_calls):
print(f"\nTool call #{i + 1}: {tool_call.name}")
print(f"Arguments: {tool_call.arguments}")
results.append(tool_call.arguments)
# For backward compatibility, return the first tool call's arguments
return results[0] if results else {}
async def main() -> None:
async with OpenAILLM(
api_key=os.getenv("OPENAI_API_KEY"),
model_name="gpt-5",
model_params={"temperature": 0},
) as llm:
# Example text containing information about a person
text = "Stella Hane is a 35-year-old software engineer who loves coding."
print("\n=== Synchronous Tool Call ===")
# Make a synchronous tool call
sync_response = llm.invoke_with_tools(
input=f"Extract information about the person from this text: {text}",
tools=TOOLS,
)
sync_result = process_tool_calls(sync_response)
print("\n=== Synchronous Tool Call Result ===")
print(json.dumps(sync_result, indent=2))
print("\n=== Asynchronous Tool Call ===")
# Make an asynchronous tool call with a different text
text2 = "Molly Hane, 32, works as a data scientist and enjoys machine learning."
async_response = await llm.ainvoke_with_tools(
input=f"Extract information about the person from this text: {text2}",
tools=TOOLS,
)
async_result = process_tool_calls(async_response)
print("\n=== Asynchronous Tool Call Result ===")
print(json.dumps(async_result, indent=2))
if __name__ == "__main__":
# Run the async main function
asyncio.run(main())

View File

@@ -0,0 +1,15 @@
from neo4j_graphrag.llm import LLMResponse, VertexAILLM
from vertexai.generative_models import GenerationConfig
generation_config = GenerationConfig(temperature=1.0)
llm = VertexAILLM(
model_name="gemini-2.0-flash-001",
generation_config=generation_config,
# add here any argument that will be passed to the
# vertexai.generative_models.GenerativeModel client
)
res: LLMResponse = llm.invoke(
"say something",
system_instruction="You are living in 3000 where AI rules the world",
)
print(res.content)

View File

@@ -0,0 +1,119 @@
# Copyright (c) "Neo4j"
# Neo4j Sweden AB [https://neo4j.com]
# #
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# #
# https://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Simple example comparing VertexAI LLM V1 (legacy) vs V2 (structured output).
This demonstrates how V2's structured output provides type-safe, validated responses
compared to V1's prompt-based JSON extraction.
Prerequisites:
- Google Cloud project with Vertex AI API enabled
- Either:
- GOOGLE_APPLICATION_CREDENTIALS environment variable set, or
- Running on GCP with appropriate service account
"""
from pydantic import BaseModel
from neo4j_graphrag.llm import VertexAILLM
from neo4j_graphrag.types import LLMMessage
from vertexai.generative_models import GenerationConfig
# Define a Pydantic model for structured output
class Movie(BaseModel):
title: str
year: int
director: str
genre: str
# =============================================================================
# V1 (Legacy): Manual JSON mode with prompt engineering
# =============================================================================
print("=" * 60)
print("V1 Legacy: Manual JSON extraction with prompt engineering")
print("=" * 60)
# V1: Use generation_config
llm_v1 = VertexAILLM(
model_name="gemini-2.5-flash",
generation_config=GenerationConfig(
response_mime_type="application/json", temperature=0
),
)
# V1 requires string input
v1_prompt = """Extract movie information and respond in JSON format.
Include: title, year, director, genre.
Text: Inception was directed by Christopher Nolan in 2010. It's a science fiction thriller."""
response_v1 = llm_v1.invoke(v1_prompt)
print(f"Response: {response_v1.content}")
# =============================================================================
# V2 (New): Structured output with Pydantic model
# =============================================================================
print("\n" + "=" * 60)
print("V2: Structured output with Pydantic model")
print("=" * 60)
# V2: Use clean LLM without constructor params
llm_v2 = VertexAILLM(model_name="gemini-2.5-flash")
# V2 uses list of LLMMessage for input
messages = [
LLMMessage(
role="user",
content="Inception was directed by Christopher Nolan in 2010. It's a science fiction thriller.",
)
]
# Pass response_format and temperature directly to invoke()
response_v2 = llm_v2.invoke(messages, response_format=Movie, temperature=0)
# Parse and validate in one step
movie = Movie.model_validate_json(response_v2.content)
print(f"Response: {response_v2.content}")
# =============================================================================
# V2 Alternative: Using JSON Schema instead of Pydantic
# =============================================================================
print("\n" + "=" * 60)
print("V2 Alternative: Structured output with JSON Schema")
print("=" * 60)
# Define a JSON schema (equivalent to the Movie Pydantic model)
# Note: VertexAI accepts raw JSON schemas (no wrapping required like OpenAI)
movie_schema = {
"type": "object",
"properties": {
"title": {"type": "string"},
"year": {"type": "integer"},
"director": {"type": "string"},
"genre": {"type": "string"},
},
"required": ["title", "year", "director", "genre"],
"additionalProperties": False,
}
# Pass JSON schema as response_format
response_v2_schema = llm_v2.invoke(
messages, response_format=movie_schema, temperature=0
)
print(f"Response: {response_v2_schema.content}")

View File

@@ -0,0 +1,141 @@
"""
Example showing how to use VertexAI tool calls with parameter extraction.
Both synchronous and asynchronous examples are provided.
"""
import asyncio
from typing import Optional
from dotenv import load_dotenv
from vertexai.generative_models import GenerationConfig
from neo4j_graphrag.llm import VertexAILLM
from neo4j_graphrag.llm.types import ToolCallResponse
from neo4j_graphrag.tool import (
Tool,
ObjectParameter,
StringParameter,
IntegerParameter,
)
# Load environment variables from .env file
load_dotenv()
# Create a custom Tool implementation for person info extraction
person_tool_parameters = ObjectParameter(
description="Parameters for extracting person information",
properties={
"name": StringParameter(description="The person's full name"),
"age": IntegerParameter(description="The person's age"),
"occupation": StringParameter(description="The person's occupation"),
},
required_properties=["name"],
additional_properties=False,
)
def run_person_tool(
name: str, age: Optional[int] = None, occupation: Optional[str] = None
) -> str:
"""A simple function that summarizes person information from input parameters."""
return f"Found person {name} with age {age} and occupation {occupation}"
person_info_tool = Tool(
name="extract_person_info",
description="Extract information about a person from text",
parameters=person_tool_parameters,
execute_func=run_person_tool,
)
company_tool_parameters = ObjectParameter(
description="Parameters for extracting company information",
properties={
"name": StringParameter(description="The company's full name"),
"industry": StringParameter(description="The company's industry"),
"creation_year": IntegerParameter(description="The company's creation year"),
},
required_properties=["name"],
additional_properties=False,
)
def run_company_tool(
name: str, industry: Optional[str] = None, creation_year: Optional[int] = None
) -> str:
"""A simple function that summarizes company information from input parameters."""
return (
f"Found company {name} operating in industry {industry} since {creation_year}"
)
company_info_tool = Tool(
name="extract_company_info",
description="Extract information about a company from text",
parameters=company_tool_parameters,
execute_func=run_company_tool,
)
# Create the tool instance
TOOLS = [person_info_tool, company_info_tool]
def process_tool_call(response: ToolCallResponse) -> str:
"""Process the tool call response and return the extracted parameters."""
if not response.tool_calls:
raise ValueError("No tool calls found in response")
tool_call = response.tool_calls[0]
print(f"\nTool called: {tool_call.name}")
print(f"Arguments: {tool_call.arguments}")
print(f"Additional content: {response.content or 'None'}")
if tool_call.name == "extract_person_info":
return person_info_tool.execute(**tool_call.arguments) # type: ignore[no-any-return]
elif tool_call.name == "extract_company_info":
return str(company_info_tool.execute(**tool_call.arguments))
else:
raise ValueError("Unknown tool call")
async def main() -> None:
# Initialize the VertexAI LLM
generation_config = GenerationConfig(temperature=0.0)
llm = VertexAILLM(
model_name="gemini-2.0-flash-001",
generation_config=generation_config,
# tool_config=ToolConfig(
# function_calling_config=ToolConfig.FunctionCallingConfig(
# mode=ToolConfig.FunctionCallingConfig.Mode.ANY,
# # allowed_function_names=["extract_person_info"],
# ))
)
# Example text containing information about a company
text1 = "Neo4j is a software company created in 2007"
print("\n=== Synchronous Tool Call ===")
# Make a synchronous tool call
sync_response = llm.invoke_with_tools(
input=f"Extract information about the person from this text: {text1}",
tools=TOOLS,
)
sync_result = process_tool_call(sync_response)
print("\n=== Synchronous Tool Call Result ===")
print(sync_result)
print("\n=== Asynchronous Tool Call ===")
# Make an asynchronous tool call with a different text about a person
text2 = "Molly Hane, 32, works as a data scientist and enjoys machine learning."
async_response = await llm.ainvoke_with_tools(
input=f"Extract information about the person from this text: {text2}",
tools=TOOLS,
)
async_result = process_tool_call(async_response)
print("\n=== Asynchronous Tool Call Result ===")
print(async_result)
if __name__ == "__main__":
# Run the async main function
asyncio.run(main())