LlamaIndex একটা Python framework, নিজের data-র ওপর RAG pipeline আর agent বানানোর জন্য। Model-এর সাথে কথা বলে LLM class দিয়ে, আর যেকোনো OpenAI-compatible server-এর জন্য আছে OpenAILike। এটাকে https://tokens.bd/v1-এ দেখিয়ে দিলে Chat Completions request Tokens-এ যায়। তবে RAG pipeline-এ একটা embedding model-ও লাগে, আর আপনি আলাদা করে না বললে LlamaIndex OpenAI-র একটা model বেছে নেয়। তাই ওই অংশের জন্য নিচে আলাদা section রাখা হয়েছে।
Documentation দেখে যাচাই করা
এই পেজ লেখা হয়েছে LlamaIndex-এর documentation আর integration package-গুলোর source ও README দেখে। 2026 সালের অক্টোবরে llama-index-llms-openai-like 0.8.1-এর সাথে মেলানো হয়েছে (release হয়েছে 1 অক্টোবর 2026-এ, লাগে llama-index-core 0.14.3 বা তার নতুন version আর Python 3.10 বা নতুন)। Code-টা documentation দেখে মেলানো হয়েছে, Tokens-এর বিরুদ্ধে শুরু থেকে শেষ পর্যন্ত চালিয়ে দেখা হয়নি।
যা যা লাগবে#
- API keys থেকে নেওয়া একটা Tokens key,
TOKENS_API_KEYনামে export করা। - /models থেকে একটা model ID, যেমন
deepseek/deepseek-v4.1-flash, আর model-এর পেজ থেকে তার context window। - RAG-এর জন্য catalog থেকে একটা embedding model ID (Embeddings দেখুন)।
pip install --upgrade llama-index-llms-openai-like
export TOKENS_API_KEY="tok_live_your_key"OpenAILike সাজান#
import os
from llama_index.core.llms import ChatMessage
from llama_index.llms.openai_like import OpenAILike
llm = OpenAILike(
model="deepseek/deepseek-v4.1-flash",
api_base="https://tokens.bd/v1",
api_key=os.environ["TOKENS_API_KEY"],
is_chat_model=True,
context_window=128000, # set this to the window shown on the model's page in /models
)
response = llm.chat(
[
ChatMessage(role="system", content="You are a precise SQL reviewer."),
ChatMessage(role="user", content="Is SELECT * in a view a problem? Two sentences."),
]
)
print(response)Integration-এর README অনুযায়ী argument-গুলো:
| Argument | কী দেবেন |
|---|---|
model | Tokens-এর model ID, /models বা GET https://tokens.bd/v1/models-এ যেভাবে লেখা আছে ঠিক সেভাবে। LlamaIndex ওটা না বদলেই পাঠায়। |
api_base | https://tokens.bd/v1। /v1 রাখুন। |
api_key | আপনার Tokens key। |
is_chat_model | True। কারণ নিচে আছে। |
context_window | Model-এর আসল context window, token হিসেবে। LlamaIndex এটা দেখে prompt আর chunk-এর মাপ ঠিক করে। |
is_function_calling_model | Model tool calling সাপোর্ট করলে আর আপনি agent বা tool ব্যবহার করলে True দিন। Default হলো False। |
দুটো default-এ অনেকেই আটকে যান:
is_chat_model-এর defaultFalse। এই অবস্থায়OpenAILikeআপনার call পাঠায় completions endpoint-এ, অর্থাৎ/v1/completions-এ। অনেক chat model এই endpoint চালায়ই না, তাই call fail করে (Legacy completions)।is_chat_model=Trueদিন, তাহলে request যাবে/v1/chat/completions-এ।context_window-এর default খুব ছোট (class-এর docstring অনুযায়ী প্রায় 3,900 token)। এটা না বদলালে LlamaIndex দরকারের চেয়ে অনেক বেশি context কাটছাঁট করে। Model-এর পেজ থেকে আসল মানটা বসিয়ে দিন।
OpenAILike তার timeout (60 সেকেন্ড) আর retry (3 বার) পায় LlamaIndex-এর OpenAI class থেকে। দুটোই constructor-এ timeout আর max_retries দিয়ে বদলানো যায়। লম্বা generation হলে timeout বাড়ান, অথবা stream করুন। Tokens উত্তর দেওয়ার আগেই upstream source-গুলোর মধ্যে নিজে failover করে (Rate limits), তাই কয়েকবার retry-ই যথেষ্ট।
পুরো pipeline-এর default বানান#
from llama_index.core import Settings
Settings.llm = llmএরপর default LLM যেখানেই লাগে (query engine, chat engine), সবকিছু Tokens-এ যাবে। চাইলে শুধু একটা engine-কেও model দিতে পারেন: index.as_query_engine(llm=llm)।
Response stream করুন#
messages = [ChatMessage(role="user", content="Give me three naming tips for Python modules.")]
for chunk in llm.stream_chat(messages):
print(chunk.delta, end="", flush=True)
print()delta হলো প্রতিটি chunk-এ আসা নতুন text। Tokens-এর stream করা response-এ token count তখনই আসে যখন request-এ সেটা চাওয়া হয় (Streaming)। Source দেখে মনে হয় না OpenAILike সেটা চায়, তাই stream করা call-এ LlamaIndex-এ হয়তো usage দেখাবে না। তবে Dashboard-এ request-টা ঠিকই রেকর্ড হয়।
Tool calling আর agent#
is_function_calling_model=True দিন, আর LlamaIndex-এর FunctionAgent-কে সাধারণ Python function দিন। Function-এর নাম, type hint আর docstring মিলিয়েই tool-এর schema তৈরি হয়।
import asyncio
import os
from llama_index.core.agent.workflow import AgentStream, FunctionAgent
from llama_index.llms.openai_like import OpenAILike
llm = OpenAILike(
model="deepseek/deepseek-v4.1-flash",
api_base="https://tokens.bd/v1",
api_key=os.environ["TOKENS_API_KEY"],
is_chat_model=True,
is_function_calling_model=True,
context_window=128000, # set this to the window shown on the model's page in /models
)
def get_weather(city: str) -> str:
"""Current weather for a city."""
return f"{city}: light rain, 29C" # replace with a real lookup
agent = FunctionAgent(
tools=[get_weather],
llm=llm,
system_prompt="You answer questions about the weather. Use the tool when you need data.",
)
async def main() -> None:
response = await agent.run(user_msg="Do I need an umbrella in Dhaka?")
print(response)
# The same agent, with streamed text:
handler = agent.run(user_msg="And in Chattogram?")
async for event in handler.stream_events():
if isinstance(event, AgentStream):
print(event.delta, end="", flush=True)
await handler
print()
asyncio.run(main())agent.run(...) একটা handler ফেরত দেয়। চূড়ান্ত উত্তরের জন্য সেটাকে await করুন। আর stream করতে চাইলে আগে handler.stream_events()-এর ওপর loop চালান, তারপর await handler করুন, LlamaIndex-এর streaming guide-এ যেমন আছে। AgentStream.delta হলো সবচেয়ে নতুন text-টুকু। আপনার model যদি tool call-সহ উত্তর stream করতে না পারে, agent বানানোর সময় streaming=False দিন। এই ক্ষেত্রে LlamaIndex-এর documentation এটাই বলেছে।
Agent প্রতিটা ধাপে model-কে একবার করে call করে। তাই যে প্রশ্নে দুটো tool call লাগে, সেটায় Tokens-এ অন্তত তিনটে request যায়, আর সবগুলো আপনার rate limit-এর হিসাবে পড়ে। Tool calling-এর জন্য এমন model লাগবে যা এটা সাপোর্ট করে (Tool calling)।
OpenAILike-এ should_use_structured_outputs=True দিলে response_format-এর মাধ্যমে structured output চালু হয়। এটা শুধু সেই model-এ দিন যা JSON schema output সাপোর্ট করে (Structured output)।
RAG-এর জন্য embeddings#
শুধু Settings.llm ঠিক করে আর কিছু না করলে VectorStoreIndex তবুও LlamaIndex-এর default দিয়েই embed করে, অর্থাৎ OpenAIEmbedding-এর মাধ্যমে OpenAI-র text-embedding-ada-002 দিয়ে। ওই call-এ লাগে OpenAI-র key, আর সেটা যায় OpenAI-তে, Tokens-এ নয়। আপনার সামনে দুটো পথ আছে।
Tokens দিয়ে embed করুন। /v1/embeddings শুধু embedding model-এর সাথে চলে। deepseek/deepseek-v4.1-flash-এর মতো chat model embedding model নয়, তাই call fail করবে। Catalog থেকে একটা embedding model খুঁজে নিন (/models-এ embed লিখে search করুন), আর Embeddings পেজের মতো ID-টা environment variable থেকে পড়ুন, কারণ catalog বদলায়। Catalog-এ কোনো embedding model না থাকলে বুঝবেন আপনার অ্যাকাউন্টে এখনো কোনোটা নেই, তখন দ্বিতীয় পথটা নিন।
pip install --upgrade llama-index-embeddings-openai-like
export EMBEDDING_MODEL="the-id-from-the-catalog"import os
from llama_index.core import Settings
from llama_index.embeddings.openai_like import OpenAILikeEmbedding
Settings.embed_model = OpenAILikeEmbedding(
model_name=os.environ["EMBEDDING_MODEL"],
api_base="https://tokens.bd/v1",
api_key=os.environ["TOKENS_API_KEY"],
embed_batch_size=10,
)এই class model নয়, model_name নেয়। model দিলে ValueError raise হয়। embed_batch_size মানে এক request-এ কয়টা text যাবে। Batch বড় হলে request কম লাগে, তবে সেটা ওই model-এর জন্য provider-এর সীমার ভেতরে থাকতে হবে। LlamaIndex-এর documentation-এ লেখা নেই: এটা কোন encoding_format চায়। Call fail করলে বা অদ্ভুত vector ফেরত এলে Embeddings পেজের base64 নোটটা পড়ুন, কারণ OpenAI client library-র default হলো base64, আর সব provider সেটা সাপোর্ট করে না। এক index-এ আলাদা আলাদা model-এর vector মেশাবেন না, আর model বদলালে আবার embed করুন।
অন্য কোথাও embed করুন। Settings.embed_model-এ অন্য একটা embedding model দিন, যেমন local কোনোটা (কী কী option আছে LlamaIndex-এর documentation-এ দেখুন), আর Tokens শুধু LLM-এর জন্য রাখুন। তবে query-র ধাপে খুঁজে পাওয়া text তখনও prompt-এর অংশ হয়ে Tokens-এ যায়, অন্য যেকোনো chat request-এর মতোই।
ঠিকমতো চলছে কি না দেখুন#
python chat.py চালান। Terminal-এ ছোট একটা উত্তর ছাপা হলে বুঝবেন key, base URL আর model ID ঠিক আছে। তারপর Dashboard-এ Usage analytics খুলুন: আপনার দেওয়া model ID-র নিচে request-টা দেখা যাওয়ার কথা। আপনার key দিয়ে কোন কোন ID চলে তা দেখতে চালান curl -H "Authorization: Bearer $TOKENS_API_KEY" https://tokens.bd/v1/models (cURL)।
Model বেছে নেওয়া#
Retrieve করা text-এর ওপর সাধারণ প্রশ্নোত্তরের জন্য বেশিরভাগ chat model-ই চলে। কিন্তু agent আর structured extraction-এ ভরসাযোগ্য tool call বা JSON output লাগে, আর সেটা model ভেদে আলাদা। কোন model কোন কাজে ভালো তা আছে Choosing a model পেজে, আর প্রতিটা model-এর context window পাবেন /models-এ তার নিজের পেজে। context_window বড় দিলে LlamaIndex এক prompt-এ বেশি retrieved chunk ঢোকাতে পারে, তবে তাতে প্রতি প্রশ্নে input token-ও বেশি খরচ হয়।
সীমা আর যা কাজ করে না#
- Model-এর নাম।
OpenAILikeআপনার দেওয়াmodelযা-ই হোক সেটাই পাঠায়, তাই ID-টা এমন হতে হবে যা Tokens চালায়। LlamaIndex কোথাও এটা catalog-এর সাথে মিলিয়ে দেখে না। - Chat model থেকে embeddings। সম্ভব নয়, ওপরে দেখুন।
- শুধু OpenAI-র জন্য integration। LlamaIndex-এর নিজস্ব
OpenAIclass-এর কিছু feature, যেমন Responses API-র class-গুলো, ধরে নেয় আপনি OpenAI-তেই আছেন। Tokens-এর জন্যOpenAILikeব্যবহার করুন। - Token গোনা। Tokens-এর বিল হয় provider যে usage জানায় তার ভিত্তিতে, LlamaIndex-এর নিজের গোনার ভিত্তিতে নয় (Token counting)।
- Hosted tool। OpenAI নিজে যে tool চালায় (hosted web search, file search), সেগুলো Tokens-এ নেই। নিজের Python tool ব্যবহার করুন।
- LlamaIndex-এর অন্য LLM class। এই পেজে শুধু
OpenAILike-এর কথা আছে। LlamaIndex-এর Anthropic class custom gateway-র জন্য documented নয়, তাই সেটা এখানে ধরা হয়নি।
সমস্যা হলে#
/v1/completions-এ 400 বা 404। is_chat_model এখনো False, তাই call যাচ্ছে completions endpoint-এ, যেটা অনেক chat model চালায়ই না। is_chat_model=True দিন।
প্রতিটা request-এ 404। api_base-এ /v1 নেই, অথবা দুবার আছে। https://tokens.bd/v1 হুবহু যেভাবে আছে সেভাবে দিন।
404 model_not_found। ID-তে বানান ভুল, নয়তো chat-এর জায়গায় embedding model (বা উল্টোটা) দিয়েছেন। GET https://tokens.bd/v1/models-এর সাথে মিলিয়ে নিন।
Indexing-এর সময় OpenAI-র key নেই বা ভুল, এমন error। Embeddings যাচ্ছে OpenAI-তে, কারণ Settings.embed_model এখনো default অবস্থায় আছে। ওপরে দেখানো মতো সেটা ঠিক করে দিন।
/v1/embeddings-এ index fail করে 400 invalid_request বা 404 model_not_found দিয়ে। OpenAILikeEmbedding-কে যে ID দিয়েছেন সেটা embedding model নয়। দেখুন Embeddings।
Agent tool না ডেকেই উত্তর দেয়, কিংবা tool calling নিয়ে error আসে। is_function_calling_model=True আছে কি না দেখুন, আর model tool সাপোর্ট করে কি না দেখুন (Tool calling)। অন্য model-ও চেষ্টা করে দেখুন।
Context নিয়ে error, কিংবা উত্তর অস্বাভাবিক ছোট। context_window default অবস্থায় আছে। Model-এর আসল window-টা দিন।
401 invalid_api_key, 402 insufficient_credits, 403 model_not_allowed_on_key, 429 window_exhausted বা concurrency_limit। এগুলো অ্যাকাউন্টের সীমা, LlamaIndex-এর সমস্যা নয়। অনেক document একসাথে parallel-এ index করলে concurrency_limit ছুঁয়ে ফেলতে পারেন। Parallelism বা worker-এর সংখ্যা কমান। দেখুন Errors আর Troubleshooting, আর Support-এ যোগাযোগ করার সময় x-tokens-request-id response header-টা সাথে দিন।