Metadata-Version: 2.4
Name: akasha_terminal
Version: 1.5
Summary: document QA(RAG) package using langchain and chromadb
Author-email: chih chuan chang <ccchang@iii.org.tw>
Project-URL: Homepage, https://github.com/iii-org/akasha
Requires-Python: <3.13,>=3.11
Description-Content-Type: text/markdown
Requires-Dist: pypdf
Requires-Dist: langchain-core<2.0,>=1.3
Requires-Dist: langchain<2.0,>=1.3
Requires-Dist: langchain-experimental<0.5,>=0.4
Requires-Dist: langchain-community<0.5,>=0.4.1
Requires-Dist: langchain-classic<2.0,>=1.0
Requires-Dist: langchain_openai<2.0,>=1.0
Requires-Dist: langchain-google-genai<5.0,>=4.0
Requires-Dist: langchain-ollama<2.0,>=1.0
Requires-Dist: langchain-anthropic<2.0,>=1.0
Requires-Dist: langchain-text-splitters<2.0,>=1.1
Requires-Dist: langchain-chroma<2.0,>=1.1
Requires-Dist: chromadb>=0.5.3
Requires-Dist: openai>=1.78.1
Requires-Dist: posthog<6.0.0
Requires-Dist: tiktoken
Requires-Dist: scikit-learn>=1.3.0
Requires-Dist: jieba3>=1.0.2
Requires-Dist: opencc-python-reimplemented==0.1.7
Requires-Dist: tqdm>=4.65.0
Requires-Dist: docx2txt==0.8
Requires-Dist: rouge==1.0.1
Requires-Dist: rouge-chinese==1.0.3
Requires-Dist: click
Requires-Dist: streamlit>=1.33.0
Requires-Dist: streamlit_option_menu>=0.3.6
Requires-Dist: rank_bm25
Requires-Dist: unstructured
Requires-Dist: python-pptx
Requires-Dist: wikipedia
Requires-Dist: numpy<2
Requires-Dist: google-genai>=1.15.0
Requires-Dist: anthropic
Requires-Dist: tavily-python
Requires-Dist: faiss-cpu
Requires-Dist: langchain-mcp-adapters<0.3,>=0.2
Requires-Dist: mlflow
Requires-Dist: json_repair
Requires-Dist: jsonpatch>=1.33
Requires-Dist: python-dotenv
Requires-Dist: pyyaml<7.0,>=6.0
Provides-Extra: light
Provides-Extra: full
Requires-Dist: langchain-huggingface>=0.1.2; extra == "full"
Requires-Dist: onnxruntime<=1.20.0; extra == "full"
Requires-Dist: sentence-transformers>=3.1.1; extra == "full"
Requires-Dist: transformers>=4.50.0; extra == "full"
Requires-Dist: accelerate>=1.7.0; extra == "full"
Requires-Dist: bert-score==0.3.13; extra == "full"
Requires-Dist: tokenizers<=0.23.0,>=0.22.0; extra == "full"
Requires-Dist: sentencepiece; extra == "full"
Requires-Dist: torch==2.2.0; platform_system == "Windows" and extra == "full"
Requires-Dist: torch==2.0.1; platform_system == "Darwin" and extra == "full"
Requires-Dist: torch==2.2.0; platform_system == "Linux" and extra == "full"
Requires-Dist: torchvision==0.17.0; platform_system == "Windows" and extra == "full"
Requires-Dist: torchvision==0.15.2; platform_system == "Darwin" and extra == "full"
Requires-Dist: torchvision==0.17.0; platform_system == "Linux" and extra == "full"
Requires-Dist: llama-cpp-python>=0.3.8; extra == "full"
Requires-Dist: auto-gptq==0.3.1; extra == "full"
Provides-Extra: llama-cpp
Requires-Dist: llama-cpp-python>=0.3.8; extra == "llama-cpp"
Provides-Extra: peft
Requires-Dist: auto-gptq==0.3.1; extra == "peft"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-asyncio; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"

# akasha

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![pypi package](https://img.shields.io/pypi/v/akasha-terminal)](https://pypi.org/project/akasha-terminal/)
[![downloads](https://img.shields.io/pypi/dm/akasha-terminal)](https://pypi.org/project/akasha-terminal/)
[![python version : 3.11%2B](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/downloads/)
![GitLab CI](https://img.shields.io/badge/gitlab%20ci-%23181717.svg?style=for-the-badge&logo=gitlab&logoColor=white)
akasha simplifies document-based Question Answering (QA) and Retrieval Augmented Generation(RAG) by harnessing the power of Large Language Models to accurately answer your queries while searching through your provided documents.

With akasha, you have the flexibility to choose from a variety of language models, embedding models, and search types. Adjusting these parameters is straightforward, allowing you to optimize your approach and discover the most effective methods for obtaining accurate answers from Large Language Models.

For the chinese manual, please visit [manual](https://tea9297.github.io/akasha/)

## Quick Start (Local Development)

If you are developing in this repository (instead of only installing from PyPI), use editable install:

```bash
cd akasha
uv venv --python 3.11
source .venv/bin/activate  # Windows PowerShell: .venv\Scripts\Activate.ps1
uv pip install -e .
```

Set at least one model API key:

```bash
export OPENAI_API_KEY="your_key"

# or
export GEMINI_API_KEY="your_key"
```

Run a quick example:

```bash
python examples/ex_rag.py
python examples/ex_agent.py
```

# Change log

- Next

    1. upgraded LangChain baseline to 1.3+
    2. unified supported providers through LangChain ChatModel integrations
    3. upgraded agents to LangChain native tool calling

- 1.1

    1. fixed `keep_logs` consistency for `ask`, `RAG`, `summary`, `websearch`, and `eval`
    2. added INFO-level runtime logging for main execution flows
    3. improved exception-path logging to ensure ERROR entries are written to log files

- 1.0

    1. bug fixes
    2. added a lightweight installation option (API-call-only mode)
    3. upgraded LangChain to 1.2

- 0.9.14

    1. function calling
    2. MCP agent support

# Installation

We recommend using Python 3.11 to run our akasha package. Supported versions are Python 3.11 and 3.12.

### Standard Installation

```shell!
###create environment
$ uv venv --python 3.11

###install akasha
$ uv pip install akasha-terminal
```

### Lightweight Installation (API-call-only, v1.0+)

```bash
### create environment
uv venv --python 3.11
source .venv/bin/activate  # Windows PowerShell: .venv\Scripts\Activate.ps1

### install lightweight mode (API-call-only)
uv pip install "akasha-terminal[light]"
```

`light` keeps Chroma-backed `RAG` and `MemoryManager`, but uses remote embedding APIs instead of the local HuggingFace/Torch stack.

### Editable Install Commands

If you are developing in this repository, use one of the following commands.

Base editable install:

```bash
uv pip install -e .
```

Editable install with `light` extras:

```bash
uv pip install -e ".[light]"
```

Editable install with `light` + development tools:

```bash
uv pip install -e ".[light,dev]"
```

Editable install with `full` extras:

```bash
uv pip install -e ".[full]"
```

Editable install with `full` + development tools:

```bash
uv pip install -e ".[full,dev]"
```

If you prefer `uv` extras syntax instead of bracket notation, these are equivalent:

```bash
uv pip install -e . --extra light
uv pip install -e . --extra full
uv pip install -e . --extra light --extra dev
uv pip install -e . --extra full --extra dev
```

Note:

- Use `".[light]"`, not `". [light]"`.
- `light` = remote-model / remote-embedding path with Chroma retained.
- `full` = local embedding / rerank / HuggingFace / Torch stack included.

If you need synchronized plain requirements files, regenerate them from `pyproject.toml`:

```bash
python scripts/sync_requirements.py
```

## API Keys

### OPENAI

If you want to use openai models or embeddings, go to [openai](https://platform.openai.com/account/api-keys) to get the API key.
You can either save `OPENAI_API_KEY=your api key` into `.env` file to current working directory or,
set as a environment variable, using `export` in bash or use `os.environ` in python.

```bash

# set a environment variable

export OPENAI_API_KEY="your api key"

```

### GEMINI

If you want to use Gemini models, set `GEMINI_API_KEY` in your `.env` file or export it in your shell.

`.env` example:

```env
GEMINI_API_KEY=your_gemini_api_key
```

Shell example:

```bash
export GEMINI_API_KEY="your_gemini_api_key"
```

### ANTHROPIC

For Anthropic models, set `ANTHROPIC_API_KEY` in `.env` or export it in your shell:

```bash
export ANTHROPIC_API_KEY="your_anthropic_api_key"
```

### AZURE OPENAI

If you want to use azure openai, go to [auzreAI](https://oai.azure.com/portal) and get you own Language API base url and key.
Also, remember to deploy all the models in [Azure OpenAI Studio](https://oai.azure.com/portal). The deployment name should be used as the model name. Save the Azure OpenAI-compatible endpoint and key separately from regular OpenAI settings.

```sh

## .env file
AZURE_OPENAI_API_KEY={your azure key}
AZURE_OPENAI_BASE_URL={your Azure OpenAI-compatible base URL}

```
And now we can run akasha in python

```python
#PYTHON3.11+
import akasha

# simple QA
ak = akasha.ask(model="gemini:gemini-2.5-flash")
response = ak(
    prompt="akasha 是什麼？",
    info=["https://github.com/iii-org/akasha"],
)

```

If you want to use a local Ollama server, Akasha supports an `ollama:` model type through Ollama's OpenAI-compatible chat API:

```python
import akasha

qa = akasha.ask(model="ollama:llama3.1")
response = qa(prompt="請用一句話介紹 Akasha")
```

By default, `ollama:<model>` uses `http://localhost:11434/v1`.
If your Ollama server is on another host, use `ollama:<base_url>@<model>`:

```python
qa = akasha.ask(model="ollama:http://192.168.1.10:11434@qwen3:8b")
```

You can also set `OLLAMA_API_BASE` to change the default server location.

Akasha uses LangChain 1.3+ ChatModel integrations for the supported providers. The
same `akasha.ask()` and `akasha.agents()` interfaces can therefore be used with
OpenAI, Gemini, Anthropic, or Ollama model names:

```python
import akasha

models = [
    "openai:gpt-4o",
    "gemini:gemini-2.5-flash",
    "anthropic:claude-3-5-sonnet-latest",
    "ollama:qwen3:8b",
]

qa = akasha.ask(model=models[0])
print(qa("請簡短介紹 Akasha。"))
```

The model factory also accepts an already configured LangChain ChatModel object
when provider-specific settings are needed.

`ask()` accepts the same thinking settings. In streaming mode it yields the same
`thinking` and `answer` event types; without streaming it returns only the final
answer string:

```python
qa = akasha.ask(
    model="gemini:gemini-2.5-flash",
    stream=True,
    thinking=True,
    thinking_budget=1024,
)

for event in qa("請分析向量資料庫是否適合這個需求。"):
    print(event)
```

And then run a RAG example:

```python
#PYTHON3.11+
import akasha
data_source = "doc/mic"
prompt = "五軸是什麼?"
ak = akasha.RAG(model="gemini:gemini-2.5-flash")
response = ak(data_source, prompt)

```

## Some models you can use

Please note that for OpenAI models, you need to set the environment variable 'OPENAI_API_KEY,' and for most Hugging Face models, a GPU is required to run the models. However, for .gguf models, you can use a CPU to run them.

```python
openai_model = "openai:gpt-3.5-turbo"  # needs OPENAI_API_KEY or AZURE_OPENAI_API_KEY + AZURE_OPENAI_BASE_URL
openai4_model = "openai:gpt-4"  # needs OPENAI_API_KEY or AZURE_OPENAI_API_KEY + AZURE_OPENAI_BASE_URL
azure_model = "azure:<deployment-name>"  # needs AZURE_OPENAI_API_KEY + AZURE_OPENAI_BASE_URL
azure_embedding = "azure:<embedding-deployment-name>"  # Azure embedding deployment
gemini_flash_model = "gemini:gemini-2.5-flash" # need environment variable "GEMINI_API_KEY"
ollama_model = "ollama:llama3.1"  # default server: http://localhost:11434/v1
ollama_remote_model = "ollama:http://192.168.1.10:11434@qwen3:8b"
huggingface_model = "hf:meta-llama/Llama-2-7b-chat-hf" #need environment variable "HUGGINGFACEHUB_API_TOKEN" to download meta-llama model
quantized_ch_llama_model = "gptq:FlagAlpha/Llama2-Chinese-13b-Chat-4bit"
taiwan_llama_gptq = "gptq:weiren119/Taiwan-LLaMa-v1.0-4bits-GPTQ"
mistral = "hf:Mistral-7B-Instruct-v0.2" 
mediatek_Breeze = "hf:MediaTek-Research/Breeze-7B-Instruct-64k-v0.1"

### If you want to use llama-cpp to run model on cpu, you can download gguf version of models 

### from https://huggingface.co/TheBloke/Llama-2-7b-Chat-GGUF  and the name behind "llama-gpu:" or "llama-cpu:"

### from https://huggingface.co/TheBloke/CodeUp-Llama-2-13B-Chat-HF-GGUF

### is the path of the downloaded .gguf file
llama_cpp_model = "llama-cpp:model/llama-2-13b-chat-hf.Q5_K_S.gguf"  
llama_cpp_model = "llama-cpp:model/llama-2-7b-chat.Q5_K_S.gguf"
llama_cpp_chinese_alpaca = "llama-cpp:model/chinese-alpaca-2-7b.Q5_K_S.gguf"
chatglm_model = "chatglm:THUDM/chatglm2-6b"

```

## Some embeddings you can use

Please noted that each embedding model has different window size, texts that over the max seq length will be truncated and won't be represent
in embedding model.

Rerank_base and rerank_large are not embedding models; instead, they compare the query to each chunk of the documents and return scores that represent the similarity. As a result, they offer higher accuracy compared to embedding models but may be slower.

```python
openai_emd = "openai:text-embedding-ada-002"  # need environment variable "OPENAI_API_KEY"  # 8192 max seq length
huggingface_emd = "hf:all-MiniLM-L6-v2" 
text2vec_ch_emd = "hf:shibing624/text2vec-base-chinese"   # 128 max seq length 
text2vec_mul_emd = "hf:shibing624/text2vec-base-multilingual"  # 256 max seq length
text2vec_ch_para_emd = "hf:shibing624/text2vec-base-chinese-paraphrase" # perform better for long text, 256 max seq length
bge_en_emd = "hf:BAAI/bge-base-en-v1.5"  # 512 max seq length
bge_ch_emd = "hf:BAAI/bge-base-zh-v1.5"  # 512 max seq length

rerank_base = "rerank:BAAI/bge-reranker-base"    # 512 max seq length
rerank_large = "rerank:BAAI/bge-reranker-large"  # 512 max seq length

```

## File Summarization

To create a summary of a text file in various formats like `.pdf`, `.txt`, or `.docx`, you can use the `Summary` class. For example, the following code uses the `map_reduce` method to generate a summary.

There are two summary types, `map_reduce` and `refine`. `map_reduce` summarizes each chunk first, then produces a final summary from all chunk summaries. `refine` summarizes chunk-by-chunk and uses the previous summary as context for the next chunk, which often improves consistency.

```python
import akasha

summ = akasha.summary(
    model="gemini:gemini-2.5-flash",
    sum_type="map_reduce",
    chunk_size=1000,
    sum_len=1000,
    language="en",
    keep_logs=True,
    verbose=True,
    max_input_tokens=8000,
)

# Content can be a URL, file, or plain text
ret = summ(content=["https://github.com/iii-org/akasha"])
```

## agent

Akasha agents use LangChain 1.3+'s `create_agent` and native tool calling. The
agent manages `AIMessage`, `ToolMessage`, tool arguments, and the model/tool loop;
`akasha.agents(...)` keeps the public non-streaming return value as a plain `str`.
Models must support native tool calling. OpenAI, Gemini, Anthropic, and compatible
Ollama models can be used when their selected model exposes that capability.

### Use Built-in Tools

```python
import akasha.agent.agent_tools as at

# Use built-in web search and JSON save tools
tool_list = [at.websearch_tool(search_engine="brave"), at.saveJSON_tool()]

agent = akasha.agents(
    tools=tool_list,
    model="gemini:gemini-2.5-flash",
    temperature=1.0,
    max_input_tokens=8000,
    verbose=True,
    keep_logs=True,
)

# Ask a question and let the agent use tools to answer
response = agent("Search for Industry 4.0 on the web and save the result to iii.json")
print(response)

# Save logs
agent.save_logs("logs.json")
```

### Define and Use a Custom Tool

```python
import akasha
from datetime import datetime

# Define a tool to get today's date
def today_f():
    now = datetime.now()
    return "today's date: " + str(now.strftime("%Y-%m-%d %H:%M:%S"))

# Create the tool
today_tool = akasha.create_tool(
    "This is the tool to get today's date, the tool doesn't have any input parameter.",
    today_f,
    "today_date_tool",
)

# Create an agent with the tool
agent = akasha.agents(
    tools=[today_tool],
    model="gemini:gemini-2.5-flash",
    temperature=1.0,
    verbose=True,
    keep_logs=True,
)

# Ask a question and let the agent use the tool
response = agent("What is today's date?")
print(response)

# Save logs
agent.save_logs("logs.json")
```

### Thinking model streaming

Thinking/reasoning content is kept out of the final answer by default. When a
provider exposes thinking content through LangChain message blocks, it is stored
in the agent logs. To observe it during streaming, pass `include_thinking=True`.
The event types are `answer`, `tool`, and optionally `thinking`.

```python
import akasha
from dotenv import load_dotenv

# thinking=True enables provider-specific thinking and automatically exposes
# thinking events when stream=True.
load_dotenv(".env")
agent = akasha.agents(
    model="gemini:gemini-2.5-flash",
    tools=[],
    stream=True,
    keep_logs=True,
    thinking=True,
    thinking_budget=1024,
)

events = agent(
    "請比較向量資料庫與關聯式資料庫，最後給出建議。",
)

for event in events:
    if event["type"] == "thinking":
        print("[thinking]", event["data"])
    elif event["type"] == "answer":
        print(event["data"], end="", flush=True)
    elif event["type"] == "tool":
        print("\n[tool]", event["data"])
```

If the selected provider or model does not return thinking blocks, no `thinking`
event is emitted; the final answer is still handled normally.

For provider-specific settings, a configured LangChain ChatModel can still be
passed directly. The following is equivalent to the convenience configuration
above:

```python
import akasha
from langchain_google_genai import ChatGoogleGenerativeAI

thinking_model = ChatGoogleGenerativeAI(
    model="gemini-2.5-flash",
    thinking_budget=1024,
    include_thoughts=True,
)

agent = akasha.agents(model=thinking_model, stream=True, keep_logs=True)
for event in agent("請分析這個問題並提出結論。", include_thinking=True):
    print(event)
```

### Use Tools from MCP Servers

```python
import asyncio
import akasha
from langchain_mcp_adapters.client import MultiServerMCPClient

MODEL = "gemini:gemini-2.5-flash"

# Define MCP server connection info
connection_info = {
    "math": {
        "command": "python",
        "args": ["cal_server.py"],
        "transport": "stdio",
    },
    "weather": {
        "url": "http://localhost:8000/sse",
        "transport": "sse",
    },
}
prompt = "tell me the weather in Taipei"

async def main():
    client = MultiServerMCPClient(connection_info)
    tools = await client.get_tools()

    agent = akasha.agents(
        model=MODEL,
        tools=tools,
        temperature=1.0,
        verbose=True,
        keep_logs=True,
    )
    response = await agent.acall(prompt)
    print(response)
    agent.save_logs("logs_agent.json")


asyncio.run(main())

```
