Skip to main content

Knowledge base

A knowledge base is a hosted vector index: you upsert documents, and agents search them by meaning to ground their answers (retrieval-augmented generation).

Asset path: aixplain/air-knowledge-base/aixplain · Marketplace card

Try it​

Create a knowledge base, add three documents, then give an agent read-only access to it.

from aixplain import Aixplain

aix = Aixplain(api_key="YOUR_API_KEY")

kb = aix.Tool(
name="Product catalog",
description="Product catalog with prices and categories.",
integration="aixplain/air-knowledge-base/aixplain",
).save()

kb.run(action="upsert", data={"records": [
{"id": "prod1", "text": "Wireless headphones with noise cancellation. Price: $199.", "metadata": {"category": "electronics", "price": 199}},
{"id": "prod2", "text": "Ergonomic office chair with lumbar support. Price: $299.", "metadata": {"category": "furniture", "price": 299}},
{"id": "prod3", "text": "Stainless steel water bottle that keeps drinks cold for 24 hours. Price: $29.", "metadata": {"category": "accessories", "price": 29}},
]})

kb.allowed_actions = ["search"]
agent = aix.Agent(
name="Product assistant",
description="Answers questions about the product catalog.",
instructions="Search the product catalog to answer. Include the price.",
tools=[kb],
).save()

result = agent.run("What electronics do you sell under $200?")
print([step["unit"]["name"] for step in result.data.steps])
print(result.data.output)
Show output

allowed_actions = ["search"] keeps the agent from writing to or deleting from the index.

Configuration​

FieldParameterDefaultNotes
Embedding modelconfig={"model": MODEL_ID}aixplain defaultSet at creation. Every document in the index uses this model.
EMBEDDING_MODEL_ID = "67efd4f92a0a850afa045af7" # BGE-M3, from the Marketplace

multilingual_kb = aix.Tool(
name="Multilingual catalog",
description="Product catalog embedded with BGE-M3.",
integration="aixplain/air-knowledge-base/aixplain",
config={"model": EMBEDDING_MODEL_ID},
).save()

Actions​

ActionWhat it does
upsertAdds or replaces documents.
searchReturns the documents closest in meaning to a query.
getReturns a document by ID.
deleteRemoves a document by ID.
countReturns the number of stored chunks.
metadataReturns every metadata field and its stored values.

Run the tool directly​

allowed_actions also limits direct calls, so reset it before you run other actions yourself.

kb.allowed_actions = []

result = kb.run(action="search", data={"query": "something to drink from", "num_results": 2})
for record in result.data:
print(record["id"], record["text"], round(record["score"], 3))
Show output

search returns a list of records with id, text, score and metadata. Use num_results to set how many come back. IDs carry a #chunk suffix because documents are split into chunks on upsert.

Prepare documents​

Each record needs text. Add an id to update or delete it later, and metadata to filter on it.

To load records from a CSV file, parse the metadata column back into a dict, because pandas reads it as a string:

import ast
import pandas as pd

df = pd.read_csv("documents.csv")
df["metadata"] = df["metadata"].apply(ast.literal_eval)

result = kb.run(action="upsert", data={"records": df.to_dict(orient="records")})
print(result.data)
Show output

Control chunking​

Upsert splits each document into chunks of 10 sentences with an overlap of 3. Pass chunking to change that, or {"enabled": False} to store each document as one chunk.

guide = {
"id": "care-guide",
"text": "Charge the headphones fully before first use. Clean the ear pads with a dry cloth. "
"Wipe the chair with a damp cloth. Wash the bottle by hand.",
}
kb.run(action="upsert", data={
"records": [guide],
"chunking": {"split_by": "sentence", "split_length": 2, "split_overlap": 0},
})

result = kb.run(action="search", data={"query": "how do I clean the bottle", "num_results": 1})
print(result.data[0]["id"], "|", result.data[0]["text"])
Show output
ParameterTypeDefaultDescription
chunking.enabledboolTrueFalse stores each document as one chunk.
chunking.split_bystr"sentence""word", "sentence", "passage", "page", "line", "string" or "regex".
chunking.split_lengthint10Units per chunk, at least 1.
chunking.split_overlapint3Units shared by neighboring chunks, from 0 to split_length - 1.
chunking.split_delimiterstrrequired for "string" and "regex"The delimiter or pattern to split on.

When you set chunking, pass split_by, split_length and split_overlap together. Each chunk must fit the embedding model's input limit (8,192 tokens for the default model).

Filter by metadata​

Add filters to a search. Conditions are combined with AND.

result = kb.run(action="search", data={
"query": "something for my desk",
"num_results": 5,
"filters": [{"field": "price", "operator": "<", "value": 250}],
})
for record in result.data:
print(record["id"], record["metadata"]["price"])
Show output

Operators: ==, !=, in, not in, >, <, >=, <=. Pass a list as the value for in and not in, and a number or an ISO 8601 date for the comparisons. Field names are case-sensitive; the metadata action lists the valid ones.

Get, delete and count​

result = kb.run(action="get", data={"id": "prod2"})
print(result.data[0]["text"])

kb.run(action="delete", data={"id": "prod2"})

result = kb.run(action="count")
print(result.data)
Show output

get returns a list of the document's chunks. delete with a document ID removes all of its chunks.

Troubleshooting​

SymptomCauseFix
Action 'get' is not allowed for this toolallowed_actions was narrowed for an agent.Set kb.allowed_actions = [] before direct calls.
maximum context length is 8192 tokens on upsertA chunk is longer than the embedding model accepts.Lower split_length, or split by "word" for text without sentence breaks.
A search returns too few resultsNo num_results set, or filters exclude matches.Set num_results and check the filters against the metadata action.
The agent answers without searchingThe instructions do not point it at the knowledge base.Tell it to search the knowledge base, and check result.data.steps.

Clean up​

agent.delete()
kb.delete()
multilingual_kb.delete()

Next steps​