Skip to main content
Open In ColabOpen on GitHub

Tilores

This notebook covers how to get started with the Tilores tools. For a more complex example you can checkout our customer insights chatbot example.

Overview

Integration details

ClassPackageSerializableJS supportPackage latest
TiloresToolstilores-langchainPyPI - Version

Setup

The integration requires the following packages:

%pip install --quiet -U tilores-langchain langchain
Note: you may need to restart the kernel to use updated packages.

Credentials

To access Tilores, you need to create and configure an instance or configure the following credentials and URLs for a read-only demo instance:

import os

os.environ["TILORES_API_URL"] = (
"https://8edvhd7rqb.execute-api.eu-central-1.amazonaws.com"
)
os.environ["TILORES_TOKEN_URL"] = (
"https://saas-umgegwho-tilores.auth.eu-central-1.amazoncognito.com/oauth2/token"
)
os.environ["TILORES_CLIENT_ID"] = "3l3i0ifjurnr58u4lgf0eaeqa3"
os.environ["TILORES_CLIENT_SECRET"] = (
"1c0g3v0u7pf1bvb7v65pauqt6s0h3vkkcf9u232u92ov3lm4aun2"
)

Instantiation

Here we show how to instantiate an instance of the Tilores tools:

from tilores import TiloresAPI
from tilores_langchain import TiloresTools

tilores = TiloresAPI.from_environ()
tilores_tools = TiloresTools(tilores)
search_tool = tilores_tools.search_tool()
edge_tool = tilores_tools.edge_tool()

Invocation

The parameters for the tilores_search tool are dependent on the configured schema within Tilores. The following examples will use the schema for the demo instance with generated data.

Invoke directly with args

The following example searches for a person called Sophie Müller in Berlin. The Tilores data contains multiple such persons and returns their known email addresses and phone numbers.

result = search_tool.invoke(
{
"searchParams": {
"name": "Sophie Müller",
"city": "Berlin",
},
"recordFieldsToQuery": {
"email": True,
"phone": True,
},
}
)
print("Number of entities:", len(result["data"]["search"]["entities"]))
for entity in result["data"]["search"]["entities"]:
print("Number of records:", len(entity["records"]))
print(
"Email Addresses:",
[record["email"] for record in entity["records"] if record.get("email")],
)
print(
"Phone Numbers:",
[record["phone"] for record in entity["records"] if record.get("phone")],
)
Number of entities: 3
Number of records: 3
Email Addresses: ['s.mueller@newcompany.de', 'sophie.mueller@email.de']
Phone Numbers: ['30987654', '30987654', '30987654']
Number of records: 5
Email Addresses: ['mueller.sophie@uni-berlin.de', 'sophie.m@newshipping.de', 's.mueller@newfinance.de']
Phone Numbers: ['30135792', '30135792']
Number of records: 2
Email Addresses: ['s.mueller@company.de']
Phone Numbers: ['30123456', '30123456']

If we're interested how the records from the first entity are related, we can use the edge_tool. Note that the Tilores entity resolution engine figured out the relation between those records automatically. Please refer to the edge documentation for more details.

edge_result = edge_tool.invoke(
{"entityID": result["data"]["search"]["entities"][0]["id"]}
)
edges = edge_result["data"]["entity"]["entity"]["edges"]
print("Number of edges:", len(edges))
print("Edges:", edges)
Number of edges: 7
Edges: ['e1f2g3h4-i5j6-k7l8-m9n0-o1p2q3r4s5t6:f2g3h4i5-j6k7-l8m9-n0o1-p2q3r4s5t6u7:L1', 'e1f2g3h4-i5j6-k7l8-m9n0-o1p2q3r4s5t6:g3h4i5j6-k7l8-m9n0-o1p2-q3r4s5t6u7v8:L4', 'e1f2g3h4-i5j6-k7l8-m9n0-o1p2q3r4s5t6:f2g3h4i5-j6k7-l8m9-n0o1-p2q3r4s5t6u7:L2', 'f2g3h4i5-j6k7-l8m9-n0o1-p2q3r4s5t6u7:g3h4i5j6-k7l8-m9n0-o1p2-q3r4s5t6u7v8:L1', 'f2g3h4i5-j6k7-l8m9-n0o1-p2q3r4s5t6u7:g3h4i5j6-k7l8-m9n0-o1p2-q3r4s5t6u7v8:L4', 'e1f2g3h4-i5j6-k7l8-m9n0-o1p2q3r4s5t6:g3h4i5j6-k7l8-m9n0-o1p2-q3r4s5t6u7v8:L1', 'e1f2g3h4-i5j6-k7l8-m9n0-o1p2q3r4s5t6:f2g3h4i5-j6k7-l8m9-n0o1-p2q3r4s5t6u7:L4']

Invoke with ToolCall

We can also invoke the tool with a model-generated ToolCall, in which case a ToolMessage will be returned:

# This is usually generated by a model, but we'll create a tool call directly for demo purposes.
model_generated_tool_call = {
"args": {
"searchParams": {
"name": "Sophie Müller",
"city": "Berlin",
},
"recordFieldsToQuery": {
"email": True,
"phone": True,
},
},
"id": "1",
"name": search_tool.name,
"type": "tool_call",
}
search_tool.invoke(model_generated_tool_call)
ToolMessage(content='{"data": {"search": {"entities": [{"id": "9601cf3b-e85f-46ab-aaa8-ffb8b46f1c5b", "hits": {"c3d4e5f6-g7h8-i9j0-k1l2-m3n4o5p6q7r8": ["L1"]}, "records": [{"email": "", "phone": "30123456"}, {"email": "s.mueller@company.de", "phone": "30123456"}]}, {"id": "03da2e11-0aa2-4d17-8aaa-7b32c52decd9", "hits": {"e1f2g3h4-i5j6-k7l8-m9n0-o1p2q3r4s5t6": ["L1"], "g3h4i5j6-k7l8-m9n0-o1p2-q3r4s5t6u7v8": ["L1"]}, "records": [{"email": "s.mueller@newcompany.de", "phone": "30987654"}, {"email": "", "phone": "30987654"}, {"email": "sophie.mueller@email.de", "phone": "30987654"}]}, {"id": "4d896fb5-0d08-4212-a043-b5deb0347106", "hits": {"j6k7l8m9-n0o1-p2q3-r4s5-t6u7v8w9x0y1": ["L1"], "l8m9n0o1-p2q3-r4s5-t6u7-v8w9x0y1z2a3": ["L1"], "m9n0o1p2-q3r4-s5t6-u7v8-w9x0y1z2a3b4": ["L1"], "n0o1p2q3-r4s5-t6u7-v8w9-x0y1z2a3b4c5": ["L1"]}, "records": [{"email": "mueller.sophie@uni-berlin.de", "phone": ""}, {"email": "sophie.m@newshipping.de", "phone": ""}, {"email": "", "phone": "30135792"}, {"email": "", "phone": ""}, {"email": "s.mueller@newfinance.de", "phone": "30135792"}]}]}}}', name='tilores_search', tool_call_id='1')

Chaining

We can use our tool in a chain by first binding it to a tool-calling model and then calling it:

pip install -qU langchain-openai
import getpass
import os

if not os.environ.get("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter API key for OpenAI: ")

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o-mini")
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableConfig, chain

prompt = ChatPromptTemplate(
[
("system", "You are a helpful assistant."),
("human", "{user_input}"),
("placeholder", "{messages}"),
]
)

# specifying tool_choice will force the model to call this tool.
llm_with_tools = llm.bind_tools([search_tool], tool_choice=search_tool.name)

llm_chain = prompt | llm_with_tools


@chain
def tool_chain(user_input: str, config: RunnableConfig):
input_ = {"user_input": user_input}
ai_msg = llm_chain.invoke(input_, config=config)
tool_msgs = search_tool.batch(ai_msg.tool_calls, config=config)
return llm_chain.invoke({**input_, "messages": [ai_msg, *tool_msgs]}, config=config)


tool_chain.invoke("Tell me the email addresses from Sophie Müller from Berlin.")

API reference

For detailed documentation of all Tilores features and configurations head to the official documentation: https://docs.tilotech.io/tilores/


Was this page helpful?