Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
987fca6
chore: drop Dify upstream submodule
MisonL Sep 20, 2026
ec5896e
build: upgrade dependencies and add quality tooling
MisonL Sep 20, 2026
4277132
feat: add credential boundary, log redaction and resource guards
MisonL Sep 20, 2026
2cb7da6
feat: unify provider factory and abstract request model
MisonL Sep 20, 2026
07cb1b5
feat: adapt provider protocols and SDK surfaces
MisonL Sep 20, 2026
982cfdc
refactor: layer runtime services and entrypoint
MisonL Sep 20, 2026
c9ea020
refactor: modernize retrieval, ETL and script annotations
MisonL Sep 20, 2026
bd877aa
docs: sync guides, example config and changelog
MisonL Sep 20, 2026
b9e3710
test: add provider, service and retrieval regressions
MisonL Sep 20, 2026
28afad0
docs: clarify Ark protocol alias in changelog
MisonL Sep 20, 2026
00744b8
fix: normalize flat tool_calls for chat completions history
MisonL Sep 20, 2026
0b3d594
fix: stop forcing tool_call ids in shared message normalization
MisonL Sep 20, 2026
191836e
fix: cover short credential keys and scrub the cached traceback
MisonL Sep 20, 2026
f5f2aee
fix: warn on retired base urls and align the remaining rerank option
MisonL Sep 20, 2026
b1c1b09
docs: record the review fixes in the 1.4.0 changelog
MisonL Sep 20, 2026
9e8c0f0
docs: spell out per-protocol tool_call id requirements
MisonL Sep 20, 2026
c36743e
fix: recognize new Claude families in sampling deprecation check
MisonL Sep 20, 2026
05de41c
chore: refresh example models against current provider catalogs
MisonL Sep 20, 2026
413193b
docs: align example keys with refreshed models and fix volc embedding
MisonL Sep 20, 2026
200ce50
fix: require a word boundary before the claude model prefix
MisonL Sep 20, 2026
e92e726
fix: describe retired base urls by their actual failure mode
MisonL Sep 21, 2026
6e1652e
fix: replace invalid builtin embedding and rerank model ids
MisonL Sep 21, 2026
92efa33
docs: correct the volcengine embedding model lifecycle note
MisonL Sep 21, 2026
d515ea4
fix: refresh siliconflow chat model to a currently listed id
MisonL Sep 21, 2026
81d6a29
test: cover the active snapshot embedding compatibility guard
MisonL Sep 21, 2026
d7d8be8
fix: redact masked credential shapes in server error messages
MisonL Sep 21, 2026
dd29972
fix: reject ark instructions with enabled caching at build time
MisonL Sep 21, 2026
e4e5b1c
chore: remove dead code left by inlined logic
MisonL Sep 21, 2026
e4264bc
docs: document base url override, snapshot guard and model lifecycle
MisonL Sep 21, 2026
7a60a0a
fix: close four credential-boundary gaps in redaction and scanning
MisonL Sep 21, 2026
3b91194
fix: enforce Ark responses guards on every construction path
MisonL Sep 21, 2026
c4222a5
fix: keep responses-only tool call semantics across normalization
MisonL Sep 21, 2026
ccc37ed
fix: redact credentials in every user-facing error path
MisonL Sep 21, 2026
2f4ebc0
test: cover the credential and provider guards fixed above
MisonL Sep 21, 2026
34b8319
fix: include the Apache 2.0 text and release teardown gaps
MisonL Sep 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,17 @@ DEFAULT_LLM_PROVIDER="openai"
# 其他可选模型密钥
ANTHROPIC_API_KEY=""
GOOGLE_API_KEY=""
# google-genai 官方别名;同时设置时 GOOGLE_API_KEY 优先
# GEMINI_API_KEY=""
# Vertex AI ADC(不使用 GOOGLE_API_KEY 时启用)
# GOOGLE_GENAI_USE_VERTEXAI="true"
# GOOGLE_CLOUD_PROJECT="your-project-id"
# GOOGLE_CLOUD_LOCATION="us-central1"
# GOOGLE_APPLICATION_CREDENTIALS="/absolute/path/service-account.json"
SILICONFLOW_API_KEY=""
QWEN_API_KEY=""
# Ark API key(与 AccessKey/SecretKey 二选一)
ARK_API_KEY=""
VOLC_ACCESS_KEY=""
VOLC_SECRET_KEY=""
JINA_API_KEY=""
Expand All @@ -21,8 +30,3 @@ GROK_API_KEY=""
# 默认嵌入模型已在 config.toml 中设置为 local-hash。
# 如需切换,请在这里覆盖 DEFAULT_EMBEDDING_PROVIDER 或在 config.toml 中修改。
# DEFAULT_EMBEDDING_PROVIDER="local-hash"

# iflow 示例
# OPENAI_API_KEY="sk-your-iflow-key"
# OPENAI_API_BASE="https://apis.iflow.cn/v1"
# DEFAULT_LLM_PROVIDER="iflow-qwen3-max"
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ htmlcov/
*wheels/
*.egg
*instance/
# PyInstaller 构建产物(scripts/build_binary_release.py 生成后即删除,不应入库)
*.spec
# 虚拟环境
/.env*
!/.env.example
Expand Down
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

74 changes: 54 additions & 20 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,66 @@
# 仓库指南 (Repository Guidelines)
# Repository Guidelines

## 项目结构与模块组织 (Project Structure & Module Organization)
本指南适用于仓库根目录的 PyRAG-Kit。项目要求 Python 3.11 或更高版本,使用 `uv` 管理依赖。

本仓库是一个 Python 3.11+ 的 RAG 工具集。核心代码位于 `src/` 目录下,按职责拆分为以下主要模块:
`src/chat/`、`src/providers/`、`src/retrieval/`、`src/etl/`、`src/ui/` 和 `src/utils/`。入口程序和脚本位于
`main.py` 和 `scripts/`。测试代码位于 `tests/`,其目录结构与源码对应。运行产物(如 `data/` 目录和生成的日志)不应提交至版本控制。
## Project Structure & Module Organization

## 构建、测试与开发命令 (Build, Test, and Development Commands)
- `main.py` 是交互式入口;`src/` 按职责划分为 `chat/`、`etl/`、`models/`、`providers/`、`retrieval/`、`retrieval_test/`、`runtime/`、`services/`、`ui/` 和 `utils/`。
- `scripts/` 放置知识库快照构建、发布打包和发布说明提取脚本;`tests/` 按源码模块组织 pytest 测试。
- `knowledge_base/` 保存本地 Markdown 原文;`data/kb/` 和 `data/logs/` 保存运行产物,均不应提交。仓库不再包含 Dify 上游子模块,Dify 相关逻辑以 `src/` 中的移植代码维护。
- 核心流程为 ETL -> embedding -> FAISS 快照 -> 混合检索 -> provider-backed chat。

- `uv sync`:根据 `pyproject.toml` 安装依赖并创建本地环境。
- `uv run main.py`:启动应用程序。
- `uv run python -m scripts.embed_knowledge_base`:重建知识库快照。
- `uv run pytest`:运行完整测试套件。
- `uv run pytest tests/test_config.py`:在迭代特定更改时运行单个测试文件。
## Build, Test, and Development Commands

## 编码风格与命名规范 (Coding Style & Naming Conventions)
```bash
uv sync
uv sync --group dev
uv run main.py --smoke-test
uv run main.py
uv run python -m scripts.embed_knowledge_base --mode standard
uv run pytest
uv run pytest tests/providers/test_factory.py
uv run python scripts/build_binary_release.py --target macos-arm64 --validate
```

遵循现有的 Python 风格:使用 4 空格缩进,公开函数必须包含明确的类型标注,命名应具有描述性。
函数、变量和模块使用 `snake_case`;类使用 `PascalCase`;常量使用 `UPPER_CASE`。保持文档字符串(docstrings)和注释简短且客观。修改代码时应贴合周围代码风格,避免引入新的格式化样式。
`standard` 也可替换为 `hierarchical`。发布目标支持 `windows-x64`、`macos-x64`、`macos-arm64`、`linux-x64` 和 `linux-arm64`;标签 `v*` 会触发 GitHub Release 工作流。
发布脚本不做跨平台交叉编译,`--target` 必须匹配当前主机或 CI runner 的系统与 CPU 架构;目标不匹配时会在清理构建产物前显式失败。

## 测试指南 (Testing Guidelines)
## Quality Checks

所有自动化测试统一使用 `pytest`。测试文件命名为 `test_*.py`,测试函数命名为 `test_*`。建议将针对特定行为的测试放在该行为相关的代码附近,特别是对于配置解析、提供商工厂、ETL 和检索逻辑。项目没有强制的覆盖率阈值;针对每次行为变更都应补充测试,并优先运行最小相关测试集。
开发依赖包含 Ruff、Bandit 和 MyPy。提交前可运行:

## 提交与拉取请求指引 (Commit & Pull Request Guidelines)
```bash
uv run ruff check main.py src scripts tests
uv run bandit -r main.py src scripts -ll
uv run mypy --cache-dir /tmp/pyrag-kit-mypy main.py src
uv run python -m compileall -q main.py src scripts tests
uv lock --check
git diff --check
```

Git 提交历史应使用约定式前缀,如 `feat:`、`refactor:`、`test:` 和 `chore:`,后接简短摘要。提交信息应具体且使用祈使句。拉取请求(PR)需说明改动内容,列出验证命令,并注明是否对配置或数据文件产生影响。仅在 UI 输出发生变化时附带截图。
MyPy 使用任务专用缓存目录,避免多个进程共享 `.mypy_cache` 造成锁等待;优先修复本次改动引入的问题,并记录未覆盖的历史基线告警。

## 安全与配置提示 (Security & Configuration Tips)
## Coding Style & Naming Conventions

严禁提交密钥或本地覆盖配置。请复制 `config.toml.example` 为本地 `config.toml`,并使用 `.env` 文件处理私密数值。`config.toml` 为本地文件,默认不纳入版本控制。将 `data/` 目录和生成的日志视为本地产物。若在 `dify/` 子目录下工作,请先阅读该目录下的 `AGENTS.md`,因为子目录指令优先于此根目录指南。
使用 4 个空格缩进、明确的公开函数类型标注和简短客观的 docstring。函数、变量和模块使用 `snake_case`,类使用 `PascalCase`,常量使用 `UPPER_CASE`。项目使用 Ruff 做 lint 检查,未配置独立 formatter;修改时遵循相邻代码风格并运行 `git diff --check`。保持服务、provider、检索和快照边界,不用静默回退或占位结果掩盖失败。

## Testing Guidelines

测试框架为 pytest,配置见 `pytest.ini`;该配置禁用未使用的 `langsmith` 插件。测试文件命名为 `test_*.py`,测试函数命名为 `test_*`。新增行为应在对应 `tests/` 子目录补充回归测试;优先运行相关文件,再运行完整 `uv run pytest`。仓库未设置强制覆盖率阈值。

## Commit & Pull Request Guidelines

提交历史使用 `feat:`、`fix:`、`docs:`、`build:`、`ci:`、`chore:` 等约定式前缀,并以简短祈使句说明变更。PR 应说明目的、影响范围和验证命令,注明配置或生成数据影响;只有 UI 输出改变时才附截图。发布相关变更同步更新 `CHANGELOG.md`。

## Security & Configuration Tips

用 `cp config.toml.example config.toml` 和 `cp .env.example .env` 创建本地配置。密钥只放环境变量或本地 `.env`,不得写入源码、示例、日志或提交。根项目框架采用 MIT;`src/etl/`、`src/retrieval/` 等 Dify 衍生部分仍须遵守 `DIFY_LICENSE`,并保留上游版权声明。移除上游子模块不改变这些许可义务。
知识快照保留 Dify 兼容的 pickle 文件格式;只从本项目生成的本地快照或明确受信的 legacy 文件加载,不导入不可信来源的 `.pkl` 文件。

## API Channel Integration

Provider 必须在 `src/providers/factory.py` 声明能力并通过对应抽象接口校验。OpenAI 兼容渠道复用 `openai` SDK;Google、Anthropic、Volcengine 使用各自 SDK;Jina 和 SiliconFlow Rerank 使用 HTTP JSON。新增或调整渠道时同步更新 `config.toml.example`、用户文档和 provider 契约测试。Google 的 Auth Token、Anthropic Beta 资源和 Ark Classification 资源都需通过显式 Facade/入口调用,不能把缺少资源挂载静默当成成功。

`local-hash` 是无需远端凭证的离线 Embedding provider,默认配置使用它构建本地知识快照。

LLM 配置可通过 `protocol = "responses"` 选择 OpenAI/Ark Responses;省略时保持 `chat_completions` 兼容行为。Responses 仅在目标 Base URL 确实提供 `/responses` 时可用,`protocol_status()` 的 `adapter_supported` 不等于真实服务端验收;兼容渠道和 Ark 都必须在 `options.server_verified_protocols` 中显式登记已验证协议。Ark Responses 可使用 SDK 支持的 `input_audio`、`input_video` 和 `image_pixel_limit`,OpenAI 兼容适配器不得把这些 Ark 专属块静默发送。Embedding 和 Rerank 配置不得填写 `protocol`。
43 changes: 43 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,49 @@

所有此项目的显著更改都将记录在此文件中。

## [1.4.0] - 2026-09-20

### Provider 与协议

- 建立统一 Provider 工厂与抽象请求模型,补齐 LLM、Embedding、Rerank 的能力声明、配置校验、缓存与同步/异步生命周期管理。
- 新增 `complete()`/`acomplete()` 高级调用入口,统一支持多轮消息、工具调用、结构化输出、多模态内容、usage 与结束原因;`invoke()`/`ainvoke()` 保留文本流兼容行为。
- 修复多轮工具调用的历史归一化:共享的 `normalize_messages` 不再强制要求工具调用带 `id`,因为 Gemini 的 `FunctionCall.id` 是可选字段且 SDK 默认 `None`,否则把上一轮工具调用回填给 Google 会在请求发出前被本地拒绝;需要 `id` 的 Chat Completions 与 Responses 改为显式校验。同一处还修复了 `input` 参数别名被静默清空,以及 `function_call`/`custom_tool_call` 类型未映射为 `function` 的问题。
- 支持 Chat Completions、Responses、Google Generate Content 和 Anthropic Messages 四类线协议;OpenAI 兼容渠道与 Ark 可通过 `protocol = "responses"` 选择 Responses,Ark 的 `ark` 取值是 Chat Completions 的别名。
- Responses 对非官方端点要求 `options.server_verified_protocols = ["responses"]` 显式登记;未登记时工厂、Provider 和资源 Facade 均在请求前拒绝,避免把本地 SDK 资源误发到未实现 `/responses` 的服务端。
- Ark Responses 在构造阶段拒绝 `instructions` 与 `caching={"type": "enabled"}` 同时出现:官方规定配置 `instructions` 后本轮请求无法写入或使用缓存,`caching` 为 `enabled` 时服务端直接报错,而 SDK 不做本地校验。错误信息会指出 `instructions` 来自 `system_prompt` 的兼容默认值,并给出改走 `messages` 的修复方式。
- 新增原生资源 Facade,显式暴露文件、批处理、缓存、向量库、token 计数、调优等 SDK 能力,不再把资源生命周期混入普通聊天请求。
- 深度适配 Google GenAI、Anthropic、Volcengine Ark、Jina 与 SiliconFlow Rerank;OpenAI 兼容渠道复用 `openai` SDK,Jina 与 SiliconFlow Rerank 使用 HTTP JSON。
- Embedding 区分文档与查询任务类型:Google 使用 `RETRIEVAL_DOCUMENT` 与 `RETRIEVAL_QUERY`。

### 安全

- 新增配置、请求与日志边界的凭证校验:模型级 `options` 与请求级扩展不得携带密钥、请求头、query 或 Base URL 覆盖,资源 Facade 的关键字与位置参数同样受检。
- 凭证键识别补齐火山引擎的 `ak`/`sk` 与 Azure 存储的 `account_key`;此前这些键可绕过请求覆盖校验,而 `api_key` 会被拒绝。
- 日志与错误信息统一脱敏常见凭证表示(Bearer、API key、URL userinfo 与 query);补齐 `ak=`/`sk=`/`account_key=` 形式,以及服务端错误里「首尾可见、中间掩码」的凭证形态(如 `sk-abc***...***xyz`,此前会原样落进日志)。
- 修复脱敏日志 formatter 的缓存泄漏:`logging.Formatter` 会把格式化后的 traceback 缓存在 `record.exc_text` 上供后续 handler 复用,先格式化后脱敏会让同一 logger 上的非脱敏 handler 输出原始凭证;现在脱敏结果会写回缓存。
- 兼容渠道不再被当作官方 OpenAI 端点放行 SDK 专属资源;仅精确匹配 `https://api.openai.com/v1` 时按 SDK 契约放行。
- 收紧失败语义:凭证、SDK 或远端调用失败时显式报错,不再以空 embedding、零分 rerank 或占位回答掩盖失败。

### 移除与调整

- 移除 Dify 上游子模块;`src/etl/`、`src/retrieval/` 等移植代码继续遵守 `DIFY_LICENSE` 并保留上游版权声明。
- 清理死代码:移除 `has_system_message`、`_configured_extra_body_keys`、`SnapshotRepository.write_stats`/`load_stats`/`load_active_manifest`,以及 `recursive_text_splitter` 中未被引用的 `DEFAULT_CHILD_CHUNK_*` 常量。这些逻辑均已在调用点内联或由框架通过装饰器调用,保留会造成同一行为的两处实现。
- 移除 iFlow 渠道及其配置示例。
- 移除 qwen rerank 配置示例;该渠道不提供 rerank 能力,调用时会显式报错。
- 发布脚本新增目标环境校验,`--target` 与主机系统/架构不匹配时在清理构建产物前显式失败,不再生成错误架构的发布包。
- Qwen Base URL 改为 OpenAI 兼容接口 `https://dashscope.aliyuncs.com/compatible-mode/v1`;Volcengine Base URL 改为 Ark API `https://ark.cn-beijing.volces.com/api/v3`。配置仍为旧值时会在加载时给出显式升级警告:DashScope 原生 `api/v1` 不提供本仓库请求的 `{base_url}/chat/completions` 路径,火山旧域名 `maas-api.ml-platform-cn-beijing.volces.com` 则已停止服务。百炼的 `/responses` 只挂在业务空间专属域名下,默认共享域名不可用,文档已补充说明。
- Jina Rerank 与 SiliconFlow Rerank 一致,`return_documents` 固定为 `True` 且不允许被 `options` 覆盖。

### 测试与文档

- 新增 Provider 协议适配、SDK 能力、凭证边界、Rerank 契约与失败语义回归测试;测试总数增至 823。
- 为活动快照的 embedding 兼容性检测补充回归测试:快照记录的 embedding provider 或模型名与当前运行配置不一致时必须显式失败,避免用错向量空间后静默产出错误检索结果。
- 引入 Ruff、Bandit 与 MyPy 到开发依赖,并补齐对应配置。
- 更新 `README.md`、`AGENTS.md` 与 `docs/`,同步协议选择、`options` 边界、原生资源入口和 Vertex ADC 配置口径。
- 核对各渠道官方现状并刷新配置示例:Google Embedding 改用 `gemini-embedding-2`(`text-embedding-004` 已于 2026-01-14 退役),OpenAI 改用 `gpt-5.6-*`(`gpt-3.5-turbo` 于 2026-10-23 退役),Anthropic 改用 `claude-sonnet-4-6`(`claude-3-5-sonnet-20240620` 已于 2025-10-28 退役),DeepSeek 改用 `deepseek-v4-pro`/`deepseek-v4-flash`(`deepseek-chat` 已于 2026-07-24 退役),火山改用 `doubao-seed-2-0-lite-260428` 与 `doubao-embedding-text-240715`(`doubao-pro-32k`、`bge-large-zh` 已不在方舟模型列表),Qwen 改用 `qwen3.8-max`/`qwen3.7-plus`,SiliconFlow 改用 `Qwen/Qwen3.5-27B`/`deepseek-ai/DeepSeek-V3.2`(复核发现 `Qwen/Qwen3-8B` 已不在该平台在售列表,其 Qwen 对话模型现从 Qwen3.5-27B 起步),Grok 改用 `grok-4.6`(`llama3-70b-8192` 实为 Groq 的 ID,不属于 xAI),Ollama 改用 `llama3.1`/`gemma3`。示例配置的键名同步改为与模型一致,模型内置默认值一并更新;内置 embedding 与 rerank 兜底值此前含无效 ID(Google 的裸名 `embedding-001`、SiliconFlow 不存在的 `alibaba/` 命名空间与已下线的 `bge-reranker-large`、Ollama 的 `llama3`),现分别改为 `gemini-embedding-2`、`BAAI/bge-large-zh-v1.5`、`BAAI/bge-reranker-v2-m3` 与 `llama3.1`。
- 需要重建知识库快照:`gemini-embedding-2` 与 `text-embedding-004` 的向量空间不兼容,旧 FAISS 索引不能复用。火山的 `doubao-embedding-text-240715` 已于 2025-12-26 停止新购(EOM),且已不在方舟「向量化能力」模型列表中;官方下线公告给出的迁移目标是 `doubao-embedding-vision-251215`,该模型同时接受纯文本输入,但它按 `/api/v3/embeddings/multimodal` 提供,与本项目使用的文本 `embeddings.create` 路径不同,迁移前需实测。embedding 模型只有 EOM 阶段、不涉及 EOS,存量接入点不受影响,因此示例配置暂未改动该值。
- 修复 Anthropic 采样字段弃用识别:家族名不再限定 `opus`/`sonnet`/`haiku`,覆盖 5 代新增的 `claude-fable-5`、`claude-mythos-5` 等命名;此前这些模型会被透传 `temperature`/`top_p`/`top_k`,而 Python SDK v1.0+ 已移除这些参数,请求会直接失败。

## [1.3.0] - 2026-03-20

### 运行与配置
Expand Down
6 changes: 5 additions & 1 deletion DIFY_LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ b. LOGO and copyright information: In the process of using Dify's frontend, you
a. The producer can adjust the open-source agreement to be more strict or relaxed as deemed necessary.
b. Your contributed code may be used for commercial purposes, including but not limited to its cloud business operations.

Apart from the specific conditions mentioned above, all other rights and restrictions follow the Apache License 2.0. Detailed information about the Apache License 2.0 can be found at http://www.apache.org/licenses/LICENSE-2.0.
Apart from the specific conditions mentioned above, all other rights and restrictions follow the Apache License 2.0.

A copy of the Apache License 2.0 is included in this repository at `licenses/APACHE-2.0.txt`
and is redistributed with every release bundle, as required by section 4(a) of that license.
The canonical text is also available at http://www.apache.org/licenses/LICENSE-2.0.

The interactive design of this product is protected by appearance patent.

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,9 @@ uv sync --group dev
uv run python scripts/build_binary_release.py --target macos-x64 --validate
```

发布工作流定义在 [`.github/workflows/release.yml`](/Volumes/Work/code/PyRAG-kit/.github/workflows/release.yml),发布说明会从 [CHANGELOG.md](/Volumes/Work/code/PyRAG-kit/CHANGELOG.md) 的对应版本节自动提取。
打包脚本不执行跨平台交叉编译,`--target` 必须与当前主机或 CI runner 的系统和 CPU 架构一致;例如 Intel macOS 使用 `macos-x64`,Apple Silicon macOS 使用 `macos-arm64`。不匹配时脚本会在清理产物前显式失败,避免生成错误架构的发布包。

发布工作流定义在 [`.github/workflows/release.yml`](./.github/workflows/release.yml),发布说明会从 [CHANGELOG.md](./CHANGELOG.md) 的对应版本节自动提取。
二进制包内默认只包含空的 `knowledge_base/` 占位目录,使用时请自行放入 Markdown 源文档后再构建知识快照。

---
Expand Down
Loading