# LlamaIndex

> LlamaIndex (Python) থেকে OpenAILike class দিয়ে Tokens ব্যবহার করুন: api_base, is_chat_model, context window, streaming, function-calling agent আর RAG-এর জন্য embeddings।

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 রাখা হয়েছে।

:::note[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](/docs/api-keys) থেকে নেওয়া একটা Tokens key, `TOKENS_API_KEY` নামে export করা।
- [/models](/models) থেকে একটা model ID, যেমন `deepseek/deepseek-v4.1-flash`, আর model-এর পেজ থেকে তার context window।
- RAG-এর জন্য catalog থেকে একটা embedding model ID ([Embeddings](#embeddings-for-rag) দেখুন)।

```bash
pip install --upgrade llama-index-llms-openai-like
export TOKENS_API_KEY="tok_live_your_key"
```

## OpenAILike সাজান

```python title="chat.py"
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](/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`-এর default `False`।** এই অবস্থায় `OpenAILike` আপনার call পাঠায় completions endpoint-এ, অর্থাৎ `/v1/completions`-এ। অনেক chat model এই endpoint চালায়ই না, তাই call fail করে ([Legacy completions](/docs/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](/docs/rate-limits)), তাই কয়েকবার retry-ই যথেষ্ট।

### পুরো pipeline-এর default বানান

```python
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 করুন

```python
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](/docs/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 তৈরি হয়।

```python title="agent.py"
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](/docs/rate-limits)-এর হিসাবে পড়ে। Tool calling-এর জন্য এমন model লাগবে যা এটা সাপোর্ট করে ([Tool calling](/docs/tool-calling))।
`OpenAILike`-এ `should_use_structured_outputs=True` দিলে `response_format`-এর মাধ্যমে structured output চালু হয়। এটা শুধু সেই model-এ দিন যা JSON schema output সাপোর্ট করে ([Structured output](/docs/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](/models)-এ `embed` লিখে search করুন), আর [Embeddings](/docs/embeddings) পেজের মতো ID-টা environment variable থেকে পড়ুন, কারণ catalog বদলায়। Catalog-এ কোনো embedding model না থাকলে বুঝবেন আপনার অ্যাকাউন্টে এখনো কোনোটা নেই, তখন দ্বিতীয় পথটা নিন।

```bash
pip install --upgrade llama-index-embeddings-openai-like
export EMBEDDING_MODEL="the-id-from-the-catalog"
```

```python
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](/docs/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](/dashboard)-এ Usage analytics খুলুন: আপনার দেওয়া model ID-র নিচে request-টা দেখা যাওয়ার কথা। আপনার key দিয়ে কোন কোন ID চলে তা দেখতে চালান `curl -H "Authorization: Bearer $TOKENS_API_KEY" https://tokens.bd/v1/models` ([cURL](/docs/curl))।

## Model বেছে নেওয়া

Retrieve করা text-এর ওপর সাধারণ প্রশ্নোত্তরের জন্য বেশিরভাগ chat model-ই চলে। কিন্তু agent আর structured extraction-এ ভরসাযোগ্য tool call বা JSON output লাগে, আর সেটা model ভেদে আলাদা। কোন model কোন কাজে ভালো তা আছে [Choosing a model](/docs/choosing-a-model) পেজে, আর প্রতিটা model-এর context window পাবেন [/models](/models)-এ তার নিজের পেজে। `context_window` বড় দিলে LlamaIndex এক prompt-এ বেশি retrieved chunk ঢোকাতে পারে, তবে তাতে প্রতি প্রশ্নে input token-ও বেশি খরচ হয়।

## সীমা আর যা কাজ করে না

- **Model-এর নাম।** `OpenAILike` আপনার দেওয়া `model` যা-ই হোক সেটাই পাঠায়, তাই ID-টা এমন হতে হবে যা Tokens চালায়। LlamaIndex কোথাও এটা catalog-এর সাথে মিলিয়ে দেখে না।
- **Chat model থেকে embeddings।** সম্ভব নয়, ওপরে দেখুন।
- **শুধু OpenAI-র জন্য integration।** LlamaIndex-এর নিজস্ব `OpenAI` class-এর কিছু feature, যেমন Responses API-র class-গুলো, ধরে নেয় আপনি OpenAI-তেই আছেন। Tokens-এর জন্য `OpenAILike` ব্যবহার করুন।
- **Token গোনা।** Tokens-এর বিল হয় provider যে usage জানায় তার ভিত্তিতে, LlamaIndex-এর নিজের গোনার ভিত্তিতে নয় ([Token counting](/docs/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](/docs/embeddings)।

**Agent tool না ডেকেই উত্তর দেয়, কিংবা tool calling নিয়ে error আসে।** `is_function_calling_model=True` আছে কি না দেখুন, আর model tool সাপোর্ট করে কি না দেখুন ([Tool calling](/docs/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](/docs/errors) আর [Troubleshooting](/docs/troubleshooting), আর [Support](/docs/support)-এ যোগাযোগ করার সময় `x-tokens-request-id` response header-টা সাথে দিন।

---
Page: https://tokens.bd/bn/docs/llamaindex
