Download API_SPECIFICATION.md from aimprabu/RAG_Documentation_Assistant: direct link, hf CLI and curl.
- Browser
- Download file 13.8 kB
-
https://huggingface.co/spaces/aimprabu/RAG_Documentation_Assistant/resolve/main/API_SPECIFICATION.md
- Command line
-
hf download hf://spaces/aimprabu/RAG_Documentation_Assistant/API_SPECIFICATION.md
-
curl -L -o API_SPECIFICATION.md https://huggingface.co/spaces/aimprabu/RAG_Documentation_Assistant/resolve/main/API_SPECIFICATION.md
API_SPECIFICATION.md — API Specification
RAG-Based Technical Documentation Assistant
Version: 1.0.0
Base URL: http://localhost:8000
OpenAPI Docs: http://localhost:8000/docs
ReDoc: http://localhost:8000/redoc
Global Response Conventions
All responses return Content-Type: application/json.
Standard Error Response
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Human-readable description",
"details": {}
},
"request_id": "req_abc123"
}
HTTP Status Code Reference
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created (new resource ingested) |
| 400 | Bad Request (invalid input) |
| 404 | Not Found |
| 422 | Unprocessable Entity (Pydantic validation failure) |
| 429 | Rate Limited |
| 503 | Service Unavailable (LLM or vector store down) |
| 500 | Internal Server Error |
Endpoints
POST /query
Purpose: Submit a natural language question and receive a grounded, cited answer from the documentation corpus.
Request Schema
{
"question": "string", // required, 1-2000 chars
"session_id": "string", // optional, UUID for conversation memory
"top_k": 5, // optional, 1-20, default 5
"max_retries": 2 // optional, 0-5, default from config
}
Pydantic Model
class QueryRequest(BaseModel):
question: str = Field(..., min_length=1, max_length=2000,
description="Natural language question")
session_id: Optional[str] = Field(None, description="Session ID for conversation memory")
top_k: Optional[int] = Field(5, ge=1, le=20, description="Number of chunks to retrieve")
max_retries: Optional[int] = Field(None, ge=0, le=5,
description="Override max retry count")
Response Schema
{
"answer": "string", // generated answer text with inline citations
"sources": [
{
"source_file": "string",
"document_id": "string",
"chunk_index": 0,
"excerpt": "string" // first 100 chars of chunk
}
],
"query_type": "string", // conceptual | how-to | troubleshooting | api-reference
"rewritten_query": "string", // the query actually used for retrieval
"retry_count": 0, // number of query rewrites performed
"is_fallback": false, // true if insufficient context was found
"response_time_ms": 1234,
"session_id": "string" // echoed back if provided
}
Validation Rules
questionmust be 1-2000 charactersquestionmust not be empty or whitespace-onlytop_kmust be between 1 and 20 (inclusive)session_idif provided must match UUID format:^[0-9a-f-]{36}$
Error Responses
| Code | Error Code | Condition |
|---|---|---|
| 422 | VALIDATION_ERROR |
question exceeds 2000 chars or is empty |
| 503 | LLM_UNAVAILABLE |
LLM provider API is down |
| 503 | VECTOR_STORE_ERROR |
ChromaDB unavailable |
| 500 | WORKFLOW_ERROR |
Unexpected error in LangGraph |
Example Request
curl -X POST http://localhost:8000/query \
-H "Content-Type: application/json" \
-d '{
"question": "How do I create a custom tool in LangChain?",
"top_k": 5
}'
Example Response (Success)
{
"answer": "To create a custom tool in LangChain, you can use the @tool decorator or inherit from the BaseTool class. [Source: langchain_docs.md]\n\nUsing the decorator approach:\n```python\nfrom langchain.tools import tool\n\n@tool\ndef my_tool(input: str) -> str:\n \"\"\"Describe what the tool does.\"\"\"\n return f\"Result: {input}\"\n```\n[Source: langchain_docs.md, chunk 12]",
"sources": [
{
"source_file": "langchain_docs.md",
"document_id": "doc_001",
"chunk_index": 12,
"excerpt": "To create a custom tool, use the @tool decorator. The function's docstring..."
}
],
"query_type": "how-to",
"rewritten_query": "LangChain custom tool creation @tool decorator BaseTool class",
"retry_count": 0,
"is_fallback": false,
"response_time_ms": 2341,
"session_id": null
}
Example Response (Fallback)
{
"answer": "I was unable to find relevant information in the documentation corpus to answer your question. Please check that your question is related to the indexed documents, or consider rephrasing it.",
"sources": [],
"query_type": "conceptual",
"rewritten_query": "React hooks useEffect tutorial",
"retry_count": 2,
"is_fallback": true,
"response_time_ms": 5876,
"session_id": null
}
POST /ingest
Purpose: Ingest a new document into the corpus. Accepts a file upload or a URL. The document is chunked, embedded, and stored in the vector store.
Request Schema (multipart/form-data)
file: File (optional) — .md, .txt, .html, .pdf, max 10MB
url: string (optional) — publicly accessible URL to fetch
At least one of file or url must be provided.
Validation Rules
- Exactly one of
fileorurlmust be provided (not both, not neither) - Allowed file extensions:
.md,.txt,.html,.pdf - Maximum file size: 10MB
- URL must be a valid
http://orhttps://URL - File content must not be empty after loading
Response Schema
{
"document_id": "string", // assigned document ID
"filename": "string", // original filename or URL-derived name
"chunks_indexed": 42, // number of chunks created and indexed
"file_size_bytes": 12345,
"status": "indexed", // indexed | failed
"message": "string", // human-readable summary
"duplicate": false // true if document was already indexed (dedup check)
}
Error Responses
| Code | Error Code | Condition |
|---|---|---|
| 400 | MISSING_SOURCE |
Neither file nor url provided |
| 400 | BOTH_SOURCES |
Both file and url provided |
| 400 | INVALID_FILE_TYPE |
File extension not allowed |
| 400 | FILE_TOO_LARGE |
File exceeds 10MB |
| 400 | EMPTY_DOCUMENT |
File has no extractable text content |
| 400 | INVALID_URL |
URL is malformed |
| 400 | URL_FETCH_FAILED |
URL could not be fetched (404, timeout, etc.) |
| 503 | VECTOR_STORE_ERROR |
ChromaDB unavailable |
Example Request (File Upload)
curl -X POST http://localhost:8000/ingest \
-F "file=@langchain_docs.md"
Example Request (URL)
curl -X POST http://localhost:8000/ingest \
-F "url=https://raw.githubusercontent.com/langchain-ai/langchain/master/README.md"
Example Response
{
"document_id": "doc_007",
"filename": "langchain_docs.md",
"chunks_indexed": 47,
"file_size_bytes": 23041,
"status": "indexed",
"message": "Document 'langchain_docs.md' successfully indexed with 47 chunks.",
"duplicate": false
}
Example Response (Duplicate)
{
"document_id": "doc_001",
"filename": "langchain_docs.md",
"chunks_indexed": 0,
"file_size_bytes": 23041,
"status": "indexed",
"message": "Document 'langchain_docs.md' was already indexed. Skipping.",
"duplicate": true
}
GET /documents
Purpose: List all documents that have been ingested into the corpus.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
status |
string | all | Filter by status: indexed, failed, all |
limit |
int | 50 | Max records to return (1-100) |
offset |
int | 0 | Pagination offset |
Response Schema
{
"documents": [
{
"document_id": "string",
"filename": "string",
"source_url": "string",
"chunk_count": 47,
"file_type": "md",
"status": "indexed",
"ingestion_timestamp": "2025-06-11T10:00:00Z",
"file_size_bytes": 23041
}
],
"total": 5,
"limit": 50,
"offset": 0
}
Error Responses
| Code | Error Code | Condition |
|---|---|---|
| 422 | VALIDATION_ERROR |
Invalid query parameter value |
| 503 | REGISTRY_ERROR |
Document registry unavailable |
Example Request
curl http://localhost:8000/documents
curl "http://localhost:8000/documents?status=indexed&limit=10"
Example Response
{
"documents": [
{
"document_id": "doc_001",
"filename": "langchain_docs.md",
"source_url": "",
"chunk_count": 47,
"file_type": "md",
"status": "indexed",
"ingestion_timestamp": "2025-06-11T10:00:00Z",
"file_size_bytes": 23041
},
{
"document_id": "doc_002",
"filename": "fastapi_tutorial.md",
"source_url": "https://fastapi.tiangolo.com/tutorial/",
"chunk_count": 31,
"file_type": "md",
"status": "indexed",
"ingestion_timestamp": "2025-06-11T10:05:00Z",
"file_size_bytes": 15600
}
],
"total": 2,
"limit": 50,
"offset": 0
}
POST /feedback
Purpose: Submit user feedback (thumbs up/down) on a generated answer. Used for offline quality monitoring.
Request Schema
{
"query": "string", // required, the question that was asked
"answer": "string", // required, the answer that was given
"rating": "thumbs_up", // required: "thumbs_up" | "thumbs_down"
"comment": "string", // optional, free text comment
"session_id": "string", // optional, for correlation
"response_time_ms": 1234 // optional, from query response
}
Pydantic Model
class FeedbackRequest(BaseModel):
query: str = Field(..., min_length=1, max_length=2000)
answer: str = Field(..., min_length=1, max_length=10000)
rating: Literal["thumbs_up", "thumbs_down"]
comment: Optional[str] = Field(None, max_length=1000)
session_id: Optional[str] = None
response_time_ms: Optional[int] = Field(None, ge=0)
Response Schema
{
"feedback_id": "string", // UUID assigned to this feedback record
"status": "recorded",
"message": "Thank you for your feedback."
}
Error Responses
| Code | Error Code | Condition |
|---|---|---|
| 422 | VALIDATION_ERROR |
rating not one of allowed values |
| 422 | VALIDATION_ERROR |
query or answer empty |
| 503 | STORAGE_ERROR |
Feedback database unavailable |
Example Request
curl -X POST http://localhost:8000/feedback \
-H "Content-Type: application/json" \
-d '{
"query": "How do I create a custom tool in LangChain?",
"answer": "To create a custom tool, use the @tool decorator...",
"rating": "thumbs_up",
"comment": "Very helpful, exactly what I needed"
}'
Example Response
{
"feedback_id": "fb_d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a",
"status": "recorded",
"message": "Thank you for your feedback."
}
GET /health
Purpose: Health check endpoint for load balancers and monitoring systems.
Response Schema
{
"status": "healthy", // healthy | degraded | unhealthy
"version": "1.0.0",
"components": {
"vector_store": "ok", // ok | error
"document_registry": "ok",
"llm_provider": "ok",
"embedding_model": "ok"
},
"corpus_size": 5, // number of indexed documents
"timestamp": "2025-06-11T10:00:00Z"
}
Example Request
curl http://localhost:8000/health
DELETE /documents/{document_id}
Purpose: Remove a document and all its chunks from the vector store and registry.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
document_id |
string | The document ID from GET /documents |
Response Schema
{
"document_id": "string",
"chunks_removed": 47,
"status": "deleted",
"message": "Document 'doc_001' and 47 chunks have been removed."
}
Error Responses
| Code | Error Code | Condition |
|---|---|---|
| 404 | DOCUMENT_NOT_FOUND |
document_id does not exist |
| 503 | VECTOR_STORE_ERROR |
ChromaDB unavailable |
Example Request
curl -X DELETE http://localhost:8000/documents/doc_001
GET /feedback
Purpose: Retrieve stored feedback records for analysis (admin use).
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
rating |
string | all | Filter: thumbs_up, thumbs_down, all |
limit |
int | 50 | Max records (1-100) |
offset |
int | 0 | Pagination offset |
Example Request
curl "http://localhost:8000/feedback?rating=thumbs_down&limit=20"
Example Response
{
"feedback": [
{
"feedback_id": "fb_abc123",
"query": "How do I install FastAPI?",
"rating": "thumbs_down",
"comment": "Answer was about the wrong version",
"created_at": "2025-06-11T11:00:00Z"
}
],
"total": 1,
"limit": 50,
"offset": 0
}
FastAPI Application Setup
# app/main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.api.routes import query, ingest, documents, feedback, health
app = FastAPI(
title="RAG Technical Documentation Assistant",
description="Self-corrective RAG system powered by LangGraph",
version="1.0.0",
docs_url="/docs",
redoc_url="/redoc",
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # restrict in production
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(query.router)
app.include_router(ingest.router)
app.include_router(documents.router)
app.include_router(feedback.router)
app.include_router(health.router)