Text Generation
Chat, summarization, and RAG optimized for African languages.
The Text Generation API is powered by Addis-፩-አሌፍ, our flagship Large Language Model.
Our model is trained on extensive native datasets to master not only the complex morphology (word structure) and syntax but also the deep **cultural context ** of Africa. It is culturally nuanced, understanding the specific way we live, interact, and communicate ensuring every response feels natural, respectful, and authentic to our reality.
Usage Guide
You can use text generation for simple one-off tasks (like translation) or complex multi-turn conversations.
Basic Request
Send a prompt and a target language to get an immediate response.
import AddisAI from "addisai";
const addis = new AddisAI();
const response = await addis.chat.completions.create({
messages: [{
role: "user",
content: "የአድዋ ጦርነት ታሪክ በአጭሩ",
}],
temperature: 0.7,
max_tokens: 500,
});
console.log(response.choices[0].message.content);from addisai import AddisAI
addis = AddisAI()
response = addis.chat.completions.create(
messages=[{
"role": "user",
"content": "የአድዋ ጦርነት ታሪክ በአጭሩ",
}],
temperature=0.7,
max_tokens=500,
)
print(response["choices"][0]["message"]["content"])curl https://api.addisassistant.com/api/v1/chat_generate \\
-H "Content-Type: application/json" \\
-H "x-api-key: $ADDIS_API_KEY" \\
-d '{
"prompt": "የአድዋ ጦርነት ታሪክ በአጭሩ",
"target_language": "am",
"generation_config": {
"temperature": 0.7,
"maxOutputTokens": 500
}
}'Multi-Turn Chat (Context)
The API is stateless. This means the model does not "remember" what you said in the previous request.
To build a chatbot that maintains context, you must append the conversation history to the conversation_history array in every new request.
The SDK accepts the same turns as messages and maps them to the native conversation history for you.
const messages = [
{ role: "user" as const, content: "ኢትዮጵያ ውስጥ ስንት ክልሎች አሉ?" },
{ role: "assistant" as const, content: "በአሁኑ ጊዜ 12 ክልሎች አሉ።" },
{ role: "user" as const, content: "የሁለተኛው ክልል ስም ማን ነው?" },
];
const response = await addis.chat.completions.create({ messages });
console.log(response.choices[0].message.content);messages = [
{"role": "user", "content": "ኢትዮጵያ ውስጥ ስንት ክልሎች አሉ?"},
{"role": "assistant", "content": "በአሁኑ ጊዜ 12 ክልሎች አሉ።"},
{"role": "user", "content": "የሁለተኛው ክልል ስም ማን ነው?"},
]
response = addis.chat.completions.create(messages=messages)
print(response["choices"][0]["message"]["content"])curl https://api.addisassistant.com/api/v1/chat_generate \\
-H "Content-Type: application/json" \\
-H "x-api-key: $ADDIS_API_KEY" \\
-d '{
"prompt": "የሁለተኛው ክልል ስም ማን ነው?",
"target_language": "am",
"conversation_history": [
{"role":"user","content":"ኢትዮጵያ ውስጥ ስንት ክልሎች አሉ?"},
{"role":"assistant","content":"በአሁኑ ጊዜ 12 ክልሎች አሉ።"}
]
}'System Instructions and Personas New
Use a persona for the assistant's identity and a system instruction for behavior, constraints, language, or output format. Conversation turns remain in messages.
Both fields are optional plain strings. persona defines who the assistant is; system defines how it should behave. The current user message supplies the task or input. System instructions are higher-level guidance than user messages, while Addis AI's platform safeguards remain in force if any instruction conflicts with them. Keep identity and behavioral rules consistent instead of asking the persona and system instruction to pull in different directions.
const response = await addis.chat.completions.create({
persona: "You are a patient Ethiopian language tutor.",
system: "Answer in Amharic, then include one short English gloss.",
messages: [{ role: "user", content: "Explain the word እንኳን." }],
});response = addis.chat.completions.create(
persona="You are a patient Ethiopian language tutor.",
system="Answer in Amharic, then include one short English gloss.",
messages=[{"role": "user", "content": "Explain the word እንኳን."}],
)curl https://api.addisassistant.com/api/v1/chat_generate \\
-H "Content-Type: application/json" \\
-H "x-api-key: $ADDIS_API_KEY" \\
-d '{
"persona":"You are a patient Ethiopian language tutor.",
"system":"Answer in Amharic, then include one short English gloss.",
"prompt":"Explain the word እንኳን.",
"target_language":"am"
}'Function Calling New
Function calling lets the model request an action that your application owns. The model never executes the function itself. Validate arguments, authorize the current user, run the function with a timeout, return the result, and cap the number of tool rounds.
Let the SDK run the tool loop
runTools and run_tools send the tool definitions, execute the matching local function, return its result to the model, and stop when the model produces a final answer.
const final = await addis.chat.runTools({
messages: [{ role: "user", content: "Check order 123 and summarize it." }],
tools: [{
type: "function",
function: {
name: "get_order_status",
description: "Fetch an order by ID.",
parameters: {
type: "object",
properties: { order_id: { type: "string" } },
required: ["order_id"],
additionalProperties: false,
},
function: async ({ order_id }) => {
const input = orderIdSchema.parse(order_id);
await authorize(currentUser, "read_order", input);
return getOrderWithTimeout(input, 5_000);
},
},
}],
maxToolRoundtrips: 5,
});
console.log(final.choices[0].message.content);def get_order_status(args):
order_id = validate_order_id(args["order_id"])
authorize(current_user, "read_order", order_id)
return get_order_with_timeout(order_id, timeout_seconds=5)
final = addis.chat.run_tools(
messages=[{
"role": "user",
"content": "Check order 123 and summarize it.",
}],
tools=[{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Fetch an order by ID.",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
"additionalProperties": False,
},
"callable": get_order_status,
},
}],
max_tool_roundtrips=5,
)
print(final["choices"][0]["message"]["content"])Or orchestrate each round yourself
Use the manual flow when an action needs an approval screen, a durable job, or application-specific retry logic.
const messages = [
{ role: "user" as const, content: "Check order 123." },
];
const tools = [{
type: "function" as const,
function: {
name: "get_order_status",
parameters: {
type: "object",
properties: { order_id: { type: "string" } },
required: ["order_id"],
additionalProperties: false,
},
},
}];
const first = await addis.chat.completions.create({
messages,
tools,
tool_choice: "auto",
});
const call = first.choices[0].message.tool_calls?.[0];
if (!call) throw new Error("The model did not request a tool.");
const args = orderArgsSchema.parse(JSON.parse(call.function.arguments));
await authorize(currentUser, call.function.name, args);
const result = await getOrderWithTimeout(args.order_id, 5_000);
const final = await addis.chat.completions.create({
tools,
messages: [
...messages,
first.choices[0].message,
{
role: "tool",
tool_call_id: call.id,
name: call.function.name,
content: JSON.stringify(result),
},
],
});import json
messages = [{"role": "user", "content": "Check order 123."}]
tools = [{
"type": "function",
"function": {
"name": "get_order_status",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
"additionalProperties": False,
},
},
}]
first = addis.chat.completions.create(
messages=messages,
tools=tools,
tool_choice="auto",
)
call = first["choices"][0]["message"]["tool_calls"][0]
args = validate_order_args(json.loads(call["function"]["arguments"]))
authorize(current_user, call["function"]["name"], args)
result = get_order_with_timeout(args["order_id"], timeout_seconds=5)
final = addis.chat.completions.create(
tools=tools,
messages=[
*messages,
first["choices"][0]["message"],
{
"role": "tool",
"tool_call_id": call["id"],
"name": call["function"]["name"],
"content": json.dumps(result),
},
],
)curl https://api.addisassistant.com/api/v1/chat_generate \
-H "Content-Type: application/json" \
-H "x-api-key: $ADDIS_API_KEY" \
-d '{
"prompt": "Check order 123.",
"target_language": "am",
"tools": [{
"type": "function",
"function": {
"name": "get_order_status",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
"additionalProperties": false
}
}
}],
"tool_choice": "auto"
}'Treat tool calls as untrusted input
Require approval for consequential actions, use idempotency for side effects, reject unknown functions and fields, set timeouts, cap tool rounds, and never expose secrets in tool results. Tool calling is currently non-streaming.
Streaming and Attachments
Set stream: true for incremental text. Use the SDK file helpers for images, documents, and audio; see Multimodal for the original upload, OCR, history, and schema guidance. Streaming cannot be combined with tools, attachments, or audio input.
const stream = await addis.chat.completions.create({
messages: [{ role: "user", content: "Tell me a short story." }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0].delta.content ?? "");
}stream = addis.chat.completions.create(
messages=[{"role": "user", "content": "Tell me a short story."}],
stream=True,
)
for chunk in stream:
print(chunk["choices"][0]["delta"].get("content", ""), end="")API Reference
Request Parameters
These parameters go in the root of your JSON body.
Prop
Type
Generation Config
Use generation_config to tune the creativity and length of the response.
Prop
Type
Response Schema
The API returns a JSON object.
{
"response_text": "The generated text response...",
"finish_reason": "stop",
"usage_metadata": {
"prompt_token_count": 12,
"candidates_token_count": 45,
"total_token_count": 57
},
"modelVersion": "Addis-፩-አሌፍ"
}Prop
Type
Token Counting
Note that for Amharic, token counts may be higher than English due to the Ge'ez script encoding. Typically 1 word ≈ 1.5 to 1.8 tokens.
Best Practices
Follow these architectural patterns to ensure production readiness.
Temperature
0.1 - 0.3Factual. Extraction, translation, and historical data.0.7 - 0.9Creative. Storytelling, brainstorming, and casual chat.Localization
Native Script: Models perform significantly better with Ge'ez input (e.g., "ሰላም") than Latin ("Selam").
Explicit Mode: Always set the target_language param to "am" or "om" to force the correct tokenizer.
Economy
1 Word ≈ 1.8 TokensAmharic is token-dense. Keep system prompts concise to reduce latency and costs.
Robustness
Retries: Implement exponential backoff for 500 or 429 status codes.
Safety: Handle finish_reason: "safety" gracefully in your UI if the model refuses a prompt.