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)
allowed_actions = ["search"] keeps the agent from writing to or deleting from the index.
Configuration
| Field | Parameter | Default | Notes |
|---|---|---|---|
| Embedding model | config={"model": MODEL_ID} | aixplain default | Set 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
| Action | What it does |
|---|---|
upsert | Adds or replaces documents. |
search | Returns the documents closest in meaning to a query. |
get | Returns a document by ID. |
delete | Removes a document by ID. |
count | Returns the number of stored chunks. |
metadata | Returns 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))
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)
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"])
| Parameter | Type | Default | Description |
|---|---|---|---|
chunking.enabled | bool | True | False stores each document as one chunk. |
chunking.split_by | str | "sentence" | "word", "sentence", "passage", "page", "line", "string" or "regex". |
chunking.split_length | int | 10 | Units per chunk, at least 1. |
chunking.split_overlap | int | 3 | Units shared by neighboring chunks, from 0 to split_length - 1. |
chunking.split_delimiter | str | required 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"])
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)
get returns a list of the document's chunks. delete with a document ID removes all of its chunks.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Action 'get' is not allowed for this tool | allowed_actions was narrowed for an agent. | Set kb.allowed_actions = [] before direct calls. |
maximum context length is 8192 tokens on upsert | A 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 results | No num_results set, or filters exclude matches. | Set num_results and check the filters against the metadata action. |
| The agent answers without searching | The 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
- Files: attach files to an agent instead of indexing them.
- API reference: tool: every parameter and method.