Upload 4 files
Browse files- Dockerfile +15 -0
- README.md +64 -10
- fgao.yaml +14 -0
- pyproject.toml +51 -0
Dockerfile
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.12-slim
|
| 2 |
+
|
| 3 |
+
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 PIP_NO_CACHE_DIR=1
|
| 4 |
+
RUN useradd --create-home --uid 1000 user
|
| 5 |
+
WORKDIR /home/user/app
|
| 6 |
+
|
| 7 |
+
COPY --chown=user pyproject.toml ./
|
| 8 |
+
COPY --chown=user src ./src
|
| 9 |
+
RUN pip install ".[server,openai]"
|
| 10 |
+
COPY --chown=user fgao.yaml ./
|
| 11 |
+
COPY --chown=user data ./data
|
| 12 |
+
|
| 13 |
+
USER user
|
| 14 |
+
EXPOSE 7860
|
| 15 |
+
CMD ["fgao", "serve", "--config", "fgao.yaml", "--host", "0.0.0.0", "--port", "7860"]
|
README.md
CHANGED
|
@@ -1,15 +1,69 @@
|
|
| 1 |
---
|
| 2 |
title: FGAO API
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
-
sdk:
|
| 7 |
-
|
| 8 |
-
python_version: '3.13'
|
| 9 |
-
app_file: app.py
|
| 10 |
pinned: false
|
| 11 |
-
|
| 12 |
-
short_description: Feedback-Greedy Agentic Orchestration
|
| 13 |
---
|
| 14 |
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
title: FGAO API
|
| 3 |
+
emoji: 🧭
|
| 4 |
+
colorFrom: indigo
|
| 5 |
+
colorTo: gray
|
| 6 |
+
sdk: docker
|
| 7 |
+
app_port: 7860
|
|
|
|
|
|
|
| 8 |
pinned: false
|
| 9 |
+
short_description: HTTP API for training-free FGAO orchestration of RAG
|
|
|
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# FGAO API
|
| 13 |
+
|
| 14 |
+
FGAO (Feedback-Greedy Agentic Orchestration) is a **retrieval-augmented question-answering API**.
|
| 15 |
+
|
| 16 |
+
## What it does
|
| 17 |
+
|
| 18 |
+
For each question, FGAO decides step by step which retrieval and LLM operations to run:
|
| 19 |
+
- **Sources:** which source to query, and how deep to search it.
|
| 20 |
+
- **Grading:** whether to grade the passages first.
|
| 21 |
+
- **Fallback:** when to fall back to a second source.
|
| 22 |
+
- **Checking:** when to check the answer against the passage it came from.
|
| 23 |
+
- **Abstaining:** when to stop and give no answer.
|
| 24 |
+
|
| 25 |
+
It returns an answer only if that answer is **grounded** in a retrieved passage and **passed a support check**; otherwise it returns `answer: null`. Every response includes the decision trace.
|
| 26 |
+
|
| 27 |
+
## Why it is supposed to be better
|
| 28 |
+
|
| 29 |
+
- **No LLM decides the control flow.** Each step is chosen by an explicit score: predicted progress on checkable goals, minus cost, plus a one-step lookahead. Decisions are cheap, deterministic and inspectable. A prompt cannot talk the pipeline out of verifying.
|
| 30 |
+
- **Feedback within the question.** When an operation fails, FGAO's estimate for it and for similar operations drops, so it escalates instead of repeating itself. Fixed pipelines such as CRAG and Self-RAG hard-code those rules.
|
| 31 |
+
- **Budget-aware.** Each operation has a cost. FGAO stops when nothing left is worth its cost, rather than running a fixed sequence.
|
| 32 |
+
- **Abstains when unsure.** An answer that is not grounded and supported is never returned.
|
| 33 |
+
- **Training-free.** There are no learned weights, so any LLM and any retriever can be swapped in.
|
| 34 |
+
|
| 35 |
+
## How to use
|
| 36 |
+
|
| 37 |
+
1. Add a Space secret `HF_TOKEN` (Settings → Variables and secrets). The LLM is called through Hugging Face Inference Providers; change `model` in `fgao.yaml` to use another model.
|
| 38 |
+
2. Optionally add `FGAO_API_KEYS=key1,key2` to require `Authorization: Bearer <key>`.
|
| 39 |
+
|
| 40 |
+
Ask with your own passages:
|
| 41 |
+
|
| 42 |
+
```bash
|
| 43 |
+
curl -X POST https://<space-host>/v1/answer -H "Content-Type: application/json" -d '{
|
| 44 |
+
"question": "What is the capital of Peru?",
|
| 45 |
+
"documents": ["Lima is the capital of Peru.", {"title": "Chile", "text": "Santiago is the capital of Chile."}],
|
| 46 |
+
"trace": false
|
| 47 |
+
}'
|
| 48 |
+
```
|
| 49 |
+
|
| 50 |
+
To ask over the built-in corpus instead (`data/kb.jsonl`, one `{"text", "title", "id"}` per line; replace it with your own), omit `documents`.
|
| 51 |
+
|
| 52 |
+
From Python:
|
| 53 |
+
|
| 54 |
+
```python
|
| 55 |
+
import requests
|
| 56 |
+
r = requests.post("https://<space-host>/v1/answer", json={"question": "...", "documents": [...]}).json()
|
| 57 |
+
r["answer"], r["support_passage"], r["trace"]
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
| endpoint | |
|
| 61 |
+
|---|---|
|
| 62 |
+
| `POST /v1/answer` | `question`, plus optional `documents`, `web_documents`, `budget`, `trace` |
|
| 63 |
+
| `POST /v1/answer/stream` | the same, as Server-Sent Events: one `step` per decision, then `result` |
|
| 64 |
+
| `POST /v1/batch` | `questions: [...]`, plus optional `documents` |
|
| 65 |
+
| `GET /v1/info`, `/health`, `/metrics`, `/docs` | configuration, health, Prometheus metrics, interactive API docs |
|
| 66 |
+
|
| 67 |
+
The `<space-host>` is shown under "Embed this Space" → "Direct URL", for example `angshul-fgao-api.hf.space`.
|
| 68 |
+
|
| 69 |
+
Library and source: https://github.com/AngshulMajumdar/FGAO
|
fgao.yaml
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# FGAO API configuration. Paths are relative to this file.
|
| 2 |
+
llm:
|
| 3 |
+
provider: openai # any OpenAI-compatible endpoint
|
| 4 |
+
base_url: https://router.huggingface.co/v1
|
| 5 |
+
model: Qwen/Qwen2.5-7B-Instruct # any chat model served by Hugging Face Inference Providers
|
| 6 |
+
api_key_env: HF_TOKEN # Space secret
|
| 7 |
+
temperature: 0
|
| 8 |
+
max_tokens: 128
|
| 9 |
+
timeout: 60
|
| 10 |
+
resilience: {attempts: 3, backoff: 0.5, timeout: 60, max_concurrency: 32}
|
| 11 |
+
kb: {type: bm25, path: data/kb.jsonl} # default corpus; requests may send their own "documents"
|
| 12 |
+
budget: 16
|
| 13 |
+
on_error: record
|
| 14 |
+
server: {max_inflight: 32, max_queue: 256, request_timeout: 300, max_batch: 64, max_documents: 500}
|
pyproject.toml
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[build-system]
|
| 2 |
+
requires = ["setuptools>=61"]
|
| 3 |
+
build-backend = "setuptools.build_meta"
|
| 4 |
+
|
| 5 |
+
[project]
|
| 6 |
+
name = "fgao"
|
| 7 |
+
version = "1.0.0"
|
| 8 |
+
description = "Feedback-Greedy Agentic Orchestration: a training-free numerical controller for RAG and tool-using pipelines"
|
| 9 |
+
readme = "README.md"
|
| 10 |
+
requires-python = ">=3.9"
|
| 11 |
+
authors = [{ name = "Angshul Majumdar", email = "angshul@iiitd.ac.in" }]
|
| 12 |
+
keywords = ["rag", "orchestration", "agents", "retrieval-augmented-generation", "langchain", "langgraph", "llm"]
|
| 13 |
+
classifiers = [
|
| 14 |
+
"Programming Language :: Python :: 3",
|
| 15 |
+
"Intended Audience :: Developers",
|
| 16 |
+
"Intended Audience :: Science/Research",
|
| 17 |
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
| 18 |
+
"Typing :: Typed",
|
| 19 |
+
]
|
| 20 |
+
dependencies = []
|
| 21 |
+
|
| 22 |
+
[project.urls]
|
| 23 |
+
Homepage = "https://angshulmajumdar.github.io/FGAO/"
|
| 24 |
+
Repository = "https://github.com/AngshulMajumdar/FGAO"
|
| 25 |
+
Documentation = "https://github.com/AngshulMajumdar/FGAO/tree/main/docs"
|
| 26 |
+
|
| 27 |
+
[project.optional-dependencies]
|
| 28 |
+
langchain = ["langchain-core>=0.3"]
|
| 29 |
+
langgraph = ["langgraph>=0.2", "langchain-core>=0.3"]
|
| 30 |
+
huggingface = ["huggingface_hub>=0.24"]
|
| 31 |
+
transformers = ["transformers>=4.40"]
|
| 32 |
+
openai = ["openai>=1.0"]
|
| 33 |
+
anthropic = ["anthropic>=0.30"]
|
| 34 |
+
demo = ["gradio>=4.44", "huggingface_hub>=0.24"]
|
| 35 |
+
server = ["fastapi>=0.110", "uvicorn[standard]>=0.29", "pyyaml>=6", "httpx>=0.27"]
|
| 36 |
+
mcp = ["mcp>=1.0"]
|
| 37 |
+
all = ["langchain-core>=0.3", "langgraph>=0.2", "huggingface_hub>=0.24", "openai>=1.0", "anthropic>=0.30",
|
| 38 |
+
"fastapi>=0.110", "uvicorn[standard]>=0.29", "pyyaml>=6", "httpx>=0.27", "mcp>=1.0"]
|
| 39 |
+
dev = ["pytest>=7"]
|
| 40 |
+
|
| 41 |
+
[project.scripts]
|
| 42 |
+
fgao = "fgao.server.cli:main"
|
| 43 |
+
|
| 44 |
+
[tool.setuptools.packages.find]
|
| 45 |
+
where = ["src"]
|
| 46 |
+
|
| 47 |
+
[tool.setuptools.package-data]
|
| 48 |
+
fgao = ["py.typed"]
|
| 49 |
+
|
| 50 |
+
[tool.pytest.ini_options]
|
| 51 |
+
testpaths = ["tests"]
|