mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-15 04:17:56 +00:00
docs: migrate to Nextra 4 and Next.js App Router
This commit is contained in:
1 parent
6b5779054d
commit
17a736a927
53 files changed
+901
-691
No files matched your search
@@ -0,0 +1,25 @@
|
||||
import { generateStaticParamsFor, importPage } from 'nextra/pages';
|
||||
|
||||
import { useMDXComponents } from '../../mdx-components';
|
||||
|
||||
export const generateStaticParams = generateStaticParamsFor('mdxPath');
|
||||
|
||||
export async function generateMetadata(props) {
|
||||
const params = await props.params;
|
||||
const { metadata } = await importPage(params?.mdxPath);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
const Wrapper = useMDXComponents().wrapper;
|
||||
|
||||
export default async function Page(props) {
|
||||
const params = await props.params;
|
||||
const result = await importPage(params?.mdxPath);
|
||||
const { default: MDXContent, metadata, sourceCode, toc } = result;
|
||||
|
||||
return (
|
||||
<Wrapper metadata={metadata} sourceCode={sourceCode} toc={toc}>
|
||||
<MDXContent {...props} params={params} />
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
import Image from 'next/image';
|
||||
import { Analytics } from '@vercel/analytics/react';
|
||||
import { Banner, Head } from 'nextra/components';
|
||||
import { getPageMap } from 'nextra/page-map';
|
||||
import { Footer, Layout, Navbar } from 'nextra-theme-docs';
|
||||
import 'nextra-theme-docs/style.css';
|
||||
|
||||
import CuteLogo from '../public/cute-docsgpt.png';
|
||||
import themeConfig from '../theme.config';
|
||||
|
||||
const github = 'https://github.com/arc53/DocsGPT';
|
||||
|
||||
export const metadata = {
|
||||
title: {
|
||||
default: 'DocsGPT Documentation',
|
||||
template: '%s - DocsGPT Documentation',
|
||||
},
|
||||
description:
|
||||
'Use DocsGPT to chat with your data. DocsGPT is a GPT-powered chatbot that can answer questions about your data.',
|
||||
};
|
||||
|
||||
const navbar = (
|
||||
<Navbar
|
||||
logo={
|
||||
<div style={{ alignItems: 'center', display: 'flex', gap: '8px' }}>
|
||||
<Image src={CuteLogo} alt="DocsGPT logo" width={28} height={28} />
|
||||
<span style={{ fontWeight: 'bold', fontSize: 18 }}>DocsGPT Docs</span>
|
||||
</div>
|
||||
}
|
||||
projectLink={github}
|
||||
chatLink="https://discord.com/invite/n5BX8dh8rU"
|
||||
/>
|
||||
);
|
||||
|
||||
const footer = (
|
||||
<Footer>
|
||||
<span>MIT {new Date().getFullYear()} © </span>
|
||||
<a href="https://www.docsgpt.cloud/" target="_blank" rel="noreferrer">
|
||||
DocsGPT
|
||||
</a>
|
||||
{' | '}
|
||||
<a href="https://github.com/arc53/DocsGPT" target="_blank" rel="noreferrer">
|
||||
GitHub
|
||||
</a>
|
||||
{' | '}
|
||||
<a href="https://blog.docsgpt.cloud/" target="_blank" rel="noreferrer">
|
||||
Blog
|
||||
</a>
|
||||
</Footer>
|
||||
);
|
||||
|
||||
export default async function RootLayout({ children }) {
|
||||
return (
|
||||
<html lang="en" dir="ltr" suppressHydrationWarning>
|
||||
<Head>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="/favicons/apple-touch-icon.png"
|
||||
/>
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png" />
|
||||
<link rel="manifest" href="/favicons/site.webmanifest" />
|
||||
<meta httpEquiv="Content-Language" content="en" />
|
||||
</Head>
|
||||
<body>
|
||||
<Layout
|
||||
banner={
|
||||
<Banner storageKey="docs-launch">
|
||||
<div className="flex justify-center items-center gap-2">
|
||||
Welcome to the new DocsGPT docs!
|
||||
</div>
|
||||
</Banner>
|
||||
}
|
||||
navbar={navbar}
|
||||
footer={footer}
|
||||
pageMap={await getPageMap()}
|
||||
{...themeConfig}
|
||||
>
|
||||
{children}
|
||||
</Layout>
|
||||
<Analytics />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client';
|
||||
|
||||
import Image from 'next/image';
|
||||
|
||||
const iconMap = {
|
||||
@@ -117,4 +119,4 @@ export function DeploymentCards({ items }) {
|
||||
`}</style>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client';
|
||||
|
||||
import Image from 'next/image';
|
||||
|
||||
const iconMap = {
|
||||
@@ -114,4 +116,4 @@ export function ToolCards({ items }) {
|
||||
`}</style>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,342 @@
|
||||
---
|
||||
title: Interacting with Agents via API
|
||||
description: Learn how to programmatically interact with DocsGPT Agents using the streaming and non-streaming API endpoints.
|
||||
---
|
||||
|
||||
import { Callout, Tabs } from 'nextra/components';
|
||||
|
||||
# Interacting with Agents via API
|
||||
|
||||
DocsGPT Agents can be accessed programmatically through API endpoints. This page covers:
|
||||
|
||||
- Non-streaming answers (`/api/answer`)
|
||||
- Streaming answers over SSE (`/stream`)
|
||||
- File/image attachments (`/api/store_attachment` + `/api/task_status` + `/stream`)
|
||||
|
||||
When you use an agent `api_key`, DocsGPT loads that agent's configuration automatically (prompt, tools, sources, default model). You usually only need to send `question` and `api_key`.
|
||||
|
||||
## Base URL
|
||||
|
||||
<Callout type="info">
|
||||
For DocsGPT Cloud, use `https://gptcloud.arc53.com` as the base URL.
|
||||
</Callout>
|
||||
|
||||
- Local: `http://localhost:7091`
|
||||
- Cloud: `https://gptcloud.arc53.com`
|
||||
|
||||
## How Request Resolution Works
|
||||
|
||||
DocsGPT resolves your request in this order:
|
||||
|
||||
1. If `api_key` is provided, DocsGPT loads the mapped agent and executes with that config.
|
||||
2. If `agent_id` is provided (typically with JWT auth), DocsGPT loads that agent if allowed.
|
||||
3. If neither is provided, DocsGPT uses request-level fields (`prompt_id`, `active_docs`, `retriever`, etc.).
|
||||
|
||||
Authentication:
|
||||
|
||||
- Agent API-key flow: include `api_key` in JSON/form payload.
|
||||
- JWT flow (if auth enabled): include `Authorization: Bearer <token>`.
|
||||
|
||||
## Endpoints
|
||||
|
||||
- `POST /api/answer` (non-streaming)
|
||||
- `POST /stream` (SSE streaming)
|
||||
- `POST /api/store_attachment` (multipart upload)
|
||||
- `GET /api/task_status?task_id=...` (Celery task polling)
|
||||
|
||||
## Request Parameters
|
||||
|
||||
Common request body fields:
|
||||
|
||||
| Field | Type | Required | Applies to | Notes |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `question` | `string` | Yes | `/api/answer`, `/stream` | User query. |
|
||||
| `api_key` | `string` | Usually | `/api/answer`, `/stream` | Recommended for agent API use. Loads agent config from key. |
|
||||
| `conversation_id` | `string` | No | `/api/answer`, `/stream` | Continue an existing conversation. |
|
||||
| `history` | `string` (JSON-encoded array) | No | `/api/answer`, `/stream` | Used for new conversations. Format: `[{\"prompt\":\"...\",\"response\":\"...\"}]`. |
|
||||
| `model_id` | `string` | No | `/api/answer`, `/stream` | Override model for this request. |
|
||||
| `save_conversation` | `boolean` | No | `/api/answer`, `/stream` | Default `true`. If `false`, no conversation is persisted. |
|
||||
| `passthrough` | `object` | No | `/api/answer`, `/stream` | Dynamic values injected into prompt templates. |
|
||||
| `prompt_id` | `string` | No | `/api/answer`, `/stream` | Ignored when `api_key` already defines prompt. |
|
||||
| `active_docs` | `string` or `string[]` | No | `/api/answer`, `/stream` | Overrides active docs when not using key-owned source config. |
|
||||
| `retriever` | `string` | No | `/api/answer`, `/stream` | Retriever type (for example `classic`). |
|
||||
| `chunks` | `number` | No | `/api/answer`, `/stream` | Retrieval chunk count, default `2`. |
|
||||
| `isNoneDoc` | `boolean` | No | `/api/answer`, `/stream` | Skip document retrieval. |
|
||||
| `agent_id` | `string` | No | `/api/answer`, `/stream` | Alternative to `api_key` when using authenticated user context. |
|
||||
|
||||
Streaming-only fields:
|
||||
|
||||
| Field | Type | Required | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| `attachments` | `string[]` | No | List of attachment IDs from `/api/task_status` success result. |
|
||||
| `index` | `number` | No | Update an existing query index. If provided, `conversation_id` is required. |
|
||||
|
||||
## Non-Streaming API (`/api/answer`)
|
||||
|
||||
`/api/answer` waits for completion and returns one JSON response.
|
||||
|
||||
<Callout type="info">
|
||||
`attachments` are currently handled through `/stream`. For file/image-attached queries, use the streaming endpoint.
|
||||
</Callout>
|
||||
|
||||
Response fields:
|
||||
|
||||
- `conversation_id`
|
||||
- `answer`
|
||||
- `sources`
|
||||
- `tool_calls`
|
||||
- `thought`
|
||||
- Optional structured output metadata (`structured`, `schema`) when enabled
|
||||
|
||||
### Examples
|
||||
|
||||
<Tabs items={['cURL', 'Python', 'JavaScript']}>
|
||||
<Tabs.Tab>
|
||||
```bash
|
||||
curl -X POST http://localhost:7091/api/answer \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"question":"your question here","api_key":"your_agent_api_key"}'
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```python
|
||||
import requests
|
||||
|
||||
API_URL = "http://localhost:7091/api/answer"
|
||||
API_KEY = "your_agent_api_key"
|
||||
QUESTION = "your question here"
|
||||
|
||||
response = requests.post(
|
||||
API_URL,
|
||||
json={"question": QUESTION, "api_key": API_KEY}
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
print(response.json())
|
||||
else:
|
||||
print(f"Error: {response.status_code}")
|
||||
print(response.text)
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```javascript
|
||||
const apiUrl = 'http://localhost:7091/api/answer';
|
||||
const apiKey = 'your_agent_api_key';
|
||||
const question = 'your question here';
|
||||
|
||||
async function getAnswer() {
|
||||
try {
|
||||
const response = await fetch(apiUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ question, api_key: apiKey }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch answer:", error);
|
||||
}
|
||||
}
|
||||
|
||||
getAnswer();
|
||||
```
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
|
||||
---
|
||||
|
||||
## Streaming API (`/stream`)
|
||||
|
||||
`/stream` returns a Server-Sent Events (SSE) stream so you can render output token-by-token.
|
||||
|
||||
### SSE Event Types
|
||||
|
||||
Each `data:` frame is JSON with `type`:
|
||||
|
||||
- `answer`: incremental answer chunk
|
||||
- `source`: source list/chunks
|
||||
- `tool_calls`: tool invocation results/metadata
|
||||
- `thought`: reasoning/thought chunk (agent dependent)
|
||||
- `structured_answer`: final structured payload (when schema mode is active)
|
||||
- `id`: final conversation ID
|
||||
- `error`: error message
|
||||
- `end`: stream is complete
|
||||
|
||||
### Examples
|
||||
|
||||
<Tabs items={['cURL', 'Python', 'JavaScript']}>
|
||||
<Tabs.Tab>
|
||||
```bash
|
||||
curl -X POST http://localhost:7091/stream \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: text/event-stream" \
|
||||
-d '{"question":"your question here","api_key":"your_agent_api_key"}'
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```python
|
||||
import requests
|
||||
import json
|
||||
|
||||
API_URL = "http://localhost:7091/stream"
|
||||
payload = {
|
||||
"question": "your question here",
|
||||
"api_key": "your_agent_api_key"
|
||||
}
|
||||
|
||||
with requests.post(API_URL, json=payload, stream=True) as r:
|
||||
for line in r.iter_lines():
|
||||
if line:
|
||||
decoded_line = line.decode('utf-8')
|
||||
if decoded_line.startswith('data: '):
|
||||
try:
|
||||
data = json.loads(decoded_line[6:])
|
||||
print(data)
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```javascript
|
||||
const apiUrl = 'http://localhost:7091/stream';
|
||||
const apiKey = 'your_agent_api_key';
|
||||
const question = 'your question here';
|
||||
|
||||
async function getStream() {
|
||||
try {
|
||||
const response = await fetch(apiUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'text/event-stream'
|
||||
},
|
||||
body: JSON.stringify({ question, api_key: apiKey }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
const chunk = decoder.decode(value, { stream: true });
|
||||
// Note: This parsing method assumes each chunk contains whole lines.
|
||||
// For a more robust production implementation, buffer the chunks
|
||||
// and process them line by line.
|
||||
const lines = chunk.split('\n');
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('data: ')) {
|
||||
try {
|
||||
const data = JSON.parse(line.substring(6));
|
||||
console.log(data);
|
||||
} catch (e) {
|
||||
console.error("Failed to parse JSON from SSE event:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch stream:", error);
|
||||
}
|
||||
}
|
||||
|
||||
getStream();
|
||||
```
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
|
||||
---
|
||||
|
||||
## Attachments API (Including Images)
|
||||
|
||||
To attach an image (or other file) to a query:
|
||||
|
||||
1. Upload file(s) to `/api/store_attachment` (multipart/form-data).
|
||||
2. Poll `/api/task_status` until `status=SUCCESS`.
|
||||
3. Read `result.attachment_id` from task result.
|
||||
4. Send that ID in `/stream` as `attachments: ["..."]`.
|
||||
|
||||
<Callout type="warning">
|
||||
Attachments are processed asynchronously. Do not call `/stream` with an attachment until its task has finished with `SUCCESS`.
|
||||
</Callout>
|
||||
|
||||
### Step 1: Upload Attachment
|
||||
|
||||
`POST /api/store_attachment`
|
||||
|
||||
- Content type: `multipart/form-data`
|
||||
- Form fields:
|
||||
- `file` (required, can be repeated for multi-file upload)
|
||||
- `api_key` (optional if JWT is present; useful for API-key-only flows)
|
||||
|
||||
Example upload (single image):
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:7091/api/store_attachment \
|
||||
-F "file=@/absolute/path/to/image.png" \
|
||||
-F "api_key=your_agent_api_key"
|
||||
```
|
||||
|
||||
Possible response (single-file upload):
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"task_id": "34f1cb56-7c7f-4d5f-a973-4ea7e65f7a10",
|
||||
"message": "File uploaded successfully. Processing started."
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: Poll Task Status
|
||||
|
||||
```bash
|
||||
curl "http://localhost:7091/api/task_status?task_id=34f1cb56-7c7f-4d5f-a973-4ea7e65f7a10"
|
||||
```
|
||||
|
||||
When complete:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "SUCCESS",
|
||||
"result": {
|
||||
"attachment_id": "67b4f8f2618dc9f19384a9e1",
|
||||
"filename": "image.png",
|
||||
"mime_type": "image/png"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Attach to `/stream` Request
|
||||
|
||||
Use the `attachment_id` in `attachments`.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:7091/stream \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: text/event-stream" \
|
||||
-d '{
|
||||
"question": "Describe this image",
|
||||
"api_key": "your_agent_api_key",
|
||||
"attachments": ["67b4f8f2618dc9f19384a9e1"]
|
||||
}'
|
||||
```
|
||||
|
||||
### Image/Attachment Behavior Notes
|
||||
|
||||
- Typical image MIME types supported for native vision flows: `image/png`, `image/jpeg`, `image/jpg`, `image/webp`, `image/gif`.
|
||||
- If the selected model/provider does not support a file type natively, DocsGPT falls back to parsed text content.
|
||||
- For providers that support images but not native PDF file attachments, DocsGPT can convert PDF pages to images (synthetic PDF support).
|
||||
- Attachments are user-scoped. Upload and query must be done under the same user context (same API key owner or same JWT user).
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -8,8 +8,7 @@ export default {
|
||||
"Extensions": "Extensions",
|
||||
"https://gptcloud.arc53.com/": {
|
||||
"title": "API",
|
||||
"href": "https://gptcloud.arc53.com/",
|
||||
"newWindow": true
|
||||
"href": "https://gptcloud.arc53.com/"
|
||||
},
|
||||
"Guides": "Guides",
|
||||
"changelog": {
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,8 @@
|
||||
import { useMDXComponents as getThemeComponents } from 'nextra-theme-docs';
|
||||
|
||||
export function useMDXComponents(components) {
|
||||
return {
|
||||
...getThemeComponents(),
|
||||
...components,
|
||||
};
|
||||
}
|
||||
+8
-8
@@ -1,9 +1,9 @@
|
||||
const withNextra = require('nextra').default({
|
||||
theme: 'nextra-theme-docs',
|
||||
themeConfig: './theme.config.jsx'
|
||||
})
|
||||
const nextra = require('nextra').default;
|
||||
|
||||
module.exports = withNextra()
|
||||
|
||||
// If you have other Next.js configurations, you can pass them as the parameter:
|
||||
// module.exports = withNextra({ /* other next.js config */ })
|
||||
const withNextra = nextra({
|
||||
// Nextra v4 config lives in app/layout + theme.config.jsx
|
||||
});
|
||||
|
||||
module.exports = withNextra({
|
||||
reactStrictMode: true,
|
||||
});
|
||||
Generated
+416
-291
File diff suppressed because it is too large.
Load diff
+2
-2
@@ -9,8 +9,8 @@
|
||||
"@vercel/analytics": "^1.1.1",
|
||||
"docsgpt-react": "^0.5.1",
|
||||
"next": "^15.5.9",
|
||||
"nextra": "^3.3.1",
|
||||
"nextra-theme-docs": "^3.3.1",
|
||||
"nextra": "^4.6.1",
|
||||
"nextra-theme-docs": "^4.6.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
|
||||
@@ -1,227 +0,0 @@
|
||||
---
|
||||
title: Interacting with Agents via API
|
||||
description: Learn how to programmatically interact with DocsGPT Agents using the streaming and non-streaming API endpoints.
|
||||
---
|
||||
|
||||
import { Callout, Tabs } from 'nextra/components';
|
||||
|
||||
# Interacting with Agents via API
|
||||
|
||||
DocsGPT Agents can be accessed programmatically through a dedicated API, allowing you to integrate their specialized capabilities into your own applications, scripts, and workflows. This guide covers the two primary methods for interacting with an agent: the streaming API for real-time responses and the non-streaming API for a single, consolidated answer.
|
||||
|
||||
When you use an API key generated for a specific agent, you do not need to pass `prompt`, `tools` etc. The agent's configuration (including its prompt, selected tools, and knowledge sources) is already associated with its unique API key.
|
||||
|
||||
### API Endpoints
|
||||
|
||||
- **Non-Streaming:** `http://localhost:7091/api/answer`
|
||||
- **Streaming:** `http://localhost:7091/stream`
|
||||
|
||||
<Callout type="info">
|
||||
For DocsGPT Cloud, use `https://gptcloud.arc53.com/` as the base URL.
|
||||
</Callout>
|
||||
|
||||
For more technical details, you can explore the API swagger documentation available for the cloud version or your local instance.
|
||||
|
||||
---
|
||||
|
||||
## Non-Streaming API (`/api/answer`)
|
||||
|
||||
This is a standard synchronous endpoint. It waits for the agent to fully process the request and returns a single JSON object with the complete answer. This is the simplest method and is ideal for backend processes where a real-time feed is not required.
|
||||
|
||||
### Request
|
||||
|
||||
- **Endpoint:** `/api/answer`
|
||||
- **Method:** `POST`
|
||||
- **Payload:**
|
||||
- `question` (string, required): The user's query or input for the agent.
|
||||
- `api_key` (string, required): The unique API key for the agent you wish to interact with.
|
||||
- `history` (string, optional): A JSON string representing the conversation history, e.g., `[{\"prompt\": \"first question\", \"answer\": \"first answer\"}]`.
|
||||
|
||||
### Response
|
||||
|
||||
A single JSON object containing:
|
||||
- `answer`: The complete, final answer from the agent.
|
||||
- `sources`: A list of sources the agent consulted.
|
||||
- `conversation_id`: The unique ID for the interaction.
|
||||
|
||||
### Examples
|
||||
|
||||
<Tabs items={['cURL', 'Python', 'JavaScript']}>
|
||||
<Tabs.Tab>
|
||||
```bash
|
||||
curl -X POST http://localhost:7091/api/answer \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"question": "your question here",
|
||||
"api_key": "your_agent_api_key"
|
||||
}'
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```python
|
||||
import requests
|
||||
|
||||
API_URL = "http://localhost:7091/api/answer"
|
||||
API_KEY = "your_agent_api_key"
|
||||
QUESTION = "your question here"
|
||||
|
||||
response = requests.post(
|
||||
API_URL,
|
||||
json={"question": QUESTION, "api_key": API_KEY}
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
print(response.json())
|
||||
else:
|
||||
print(f"Error: {response.status_code}")
|
||||
print(response.text)
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```javascript
|
||||
const apiUrl = 'http://localhost:7091/api/answer';
|
||||
const apiKey = 'your_agent_api_key';
|
||||
const question = 'your question here';
|
||||
|
||||
async function getAnswer() {
|
||||
try {
|
||||
const response = await fetch(apiUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ question, api_key: apiKey }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch answer:", error);
|
||||
}
|
||||
}
|
||||
|
||||
getAnswer();
|
||||
```
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
|
||||
---
|
||||
|
||||
## Streaming API (`/stream`)
|
||||
|
||||
The `/stream` endpoint uses Server-Sent Events (SSE) to push data in real-time. This is ideal for applications where you want to display the response as it's being generated, such as in a live chatbot interface.
|
||||
|
||||
### Request
|
||||
|
||||
- **Endpoint:** `/stream`
|
||||
- **Method:** `POST`
|
||||
- **Payload:** Same as the non-streaming API.
|
||||
|
||||
### Response (SSE Stream)
|
||||
|
||||
The stream consists of multiple `data:` events, each containing a JSON object. Your client should listen for these events and process them based on their `type`.
|
||||
|
||||
**Event Types:**
|
||||
- `answer`: A chunk of the agent's final answer.
|
||||
- `source`: A document or source used by the agent.
|
||||
- `thought`: A reasoning step from the agent (for ReAct agents).
|
||||
- `id`: The unique `conversation_id` for the interaction.
|
||||
- `error`: An error message.
|
||||
- `end`: A final message indicating the stream has concluded.
|
||||
|
||||
### Examples
|
||||
|
||||
<Tabs items={['cURL', 'Python', 'JavaScript']}>
|
||||
<Tabs.Tab>
|
||||
```bash
|
||||
curl -X POST http://localhost:7091/stream \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: text/event-stream" \
|
||||
-d '{
|
||||
"question": "your question here",
|
||||
"api_key": "your_agent_api_key"
|
||||
}'
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```python
|
||||
import requests
|
||||
import json
|
||||
|
||||
API_URL = "http://localhost:7091/stream"
|
||||
payload = {
|
||||
"question": "your question here",
|
||||
"api_key": "your_agent_api_key"
|
||||
}
|
||||
|
||||
with requests.post(API_URL, json=payload, stream=True) as r:
|
||||
for line in r.iter_lines():
|
||||
if line:
|
||||
decoded_line = line.decode('utf-8')
|
||||
if decoded_line.startswith('data: '):
|
||||
try:
|
||||
data = json.loads(decoded_line[6:])
|
||||
print(data)
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```javascript
|
||||
const apiUrl = 'http://localhost:7091/stream';
|
||||
const apiKey = 'your_agent_api_key';
|
||||
const question = 'your question here';
|
||||
|
||||
async function getStream() {
|
||||
try {
|
||||
const response = await fetch(apiUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'text/event-stream'
|
||||
},
|
||||
// Corrected line: 'apiKey' is changed to 'api_key'
|
||||
body: JSON.stringify({ question, api_key: apiKey }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
const chunk = decoder.decode(value, { stream: true });
|
||||
// Note: This parsing method assumes each chunk contains whole lines.
|
||||
// For a more robust production implementation, buffer the chunks
|
||||
// and process them line by line.
|
||||
const lines = chunk.split('\n');
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('data: ')) {
|
||||
try {
|
||||
const data = JSON.parse(line.substring(6));
|
||||
console.log(data);
|
||||
} catch (e) {
|
||||
console.error("Failed to parse JSON from SSE event:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch stream:", error);
|
||||
}
|
||||
}
|
||||
|
||||
getStream();
|
||||
```
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
@@ -1,10 +0,0 @@
|
||||
import { DocsGPTWidget } from "docsgpt-react";
|
||||
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
return (
|
||||
<>
|
||||
<Component {...pageProps} />
|
||||
<DocsGPTWidget showSources={true} apiKey="5d8270cb-735f-484e-9dc9-5b407f24e652" theme="dark" size="medium" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
+5
-148
@@ -1,161 +1,18 @@
|
||||
import Image from 'next/image'
|
||||
import { Analytics } from '@vercel/analytics/react';
|
||||
|
||||
const github = 'https://github.com/arc53/DocsGPT';
|
||||
|
||||
|
||||
|
||||
|
||||
import { useConfig, useTheme } from 'nextra-theme-docs';
|
||||
import CuteLogo from './public/cute-docsgpt.png';
|
||||
const Logo = ({ height, width }) => {
|
||||
const { theme } = useTheme();
|
||||
return (
|
||||
<div style={{ alignItems: 'center', display: 'flex', gap: '8px' }}>
|
||||
<Image src={CuteLogo} alt="DocsGPT logo" width={width} height={height} />
|
||||
|
||||
<span style={{ fontWeight: 'bold', fontSize: 18 }}>DocsGPT Docs</span>
|
||||
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const config = {
|
||||
docsRepositoryBase: `${github}/blob/main/docs`,
|
||||
chat: {
|
||||
link: 'https://discord.com/invite/n5BX8dh8rU',
|
||||
},
|
||||
banner: {
|
||||
key: 'docs-launch',
|
||||
text: (
|
||||
<div className="flex justify-center items-center gap-2">
|
||||
Welcome to the new DocsGPT 🦖 docs! 👋
|
||||
</div>
|
||||
),
|
||||
},
|
||||
toc: {
|
||||
float: true,
|
||||
},
|
||||
project: {
|
||||
link: github,
|
||||
},
|
||||
darkMode: true,
|
||||
nextThemes: {
|
||||
defaultTheme: 'dark',
|
||||
},
|
||||
primaryHue: {
|
||||
dark: 207,
|
||||
light: 212,
|
||||
},
|
||||
footer: {
|
||||
text: (
|
||||
<div>
|
||||
<span>MIT {new Date().getFullYear()} © </span>
|
||||
<a href="https://www.docsgpt.cloud/" target="_blank">
|
||||
DocsGPT
|
||||
</a>
|
||||
{' | '}
|
||||
<a href="https://github.com/arc53/DocsGPT" target="_blank">
|
||||
GitHub
|
||||
</a>
|
||||
{' | '}
|
||||
<a href="https://blog.docsgpt.cloud/" target="_blank">
|
||||
Blog
|
||||
</a>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
editLink: {
|
||||
content: 'Edit this page on GitHub',
|
||||
},
|
||||
logo() {
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<Logo width={28} height={28} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
useNextSeoProps() {
|
||||
return {
|
||||
titleTemplate: `%s - DocsGPT Documentation`,
|
||||
};
|
||||
},
|
||||
|
||||
head() {
|
||||
const { frontMatter } = useConfig();
|
||||
const { theme } = useTheme();
|
||||
const title = frontMatter?.title || 'Chat with your data with DocsGPT';
|
||||
const description =
|
||||
frontMatter?.description ||
|
||||
'Use DocsGPT to chat with your data. DocsGPT is a GPT powered chatbot that can answer questions about your data.'
|
||||
const image = '/cute-docsgpt.png';
|
||||
|
||||
const composedTitle = `${title} – DocsGPT Documentation`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href={`/favicons/apple-touch-icon.png`}
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="32x32"
|
||||
href={`/favicons/favicon-32x32.png`}
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="16x16"
|
||||
href={`/favicons/favicon-16x16.png`}
|
||||
/>
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
<meta name="msapplication-TileColor" content="#00a300" />
|
||||
<link rel="manifest" href={`/favicons/site.webmanifest`} />
|
||||
<meta httpEquiv="Content-Language" content="en" />
|
||||
<meta name="title" content={composedTitle} />
|
||||
<meta name="description" content={description} />
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@ATushynski" />
|
||||
<meta name="twitter:image" content={image} />
|
||||
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:title" content={composedTitle} />
|
||||
<meta property="og:image" content={image} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta
|
||||
name="apple-mobile-web-app-title"
|
||||
content="DocsGPT Documentation"
|
||||
/>
|
||||
|
||||
</>
|
||||
);
|
||||
},
|
||||
sidebar: {
|
||||
defaultMenuCollapseLevel: 1,
|
||||
titleComponent: ({ title, type }) =>
|
||||
type === 'separator' ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<Logo height={10} width={10} />
|
||||
{title}
|
||||
<Analytics />
|
||||
</div>
|
||||
|
||||
) : (
|
||||
<>{title}
|
||||
<Analytics />
|
||||
</>
|
||||
|
||||
),
|
||||
},
|
||||
|
||||
gitTimestamp: ({ timestamp }) => (
|
||||
<>Last updated on {timestamp.toLocaleDateString()}</>
|
||||
),
|
||||
toc: {
|
||||
float: true,
|
||||
},
|
||||
editLink: 'Edit this page on GitHub',
|
||||
};
|
||||
|
||||
export default config;
|
||||
export default config;
|
||||
@@ -3,4 +3,5 @@ VITE_BASE_URL=http://localhost:5173
|
||||
VITE_API_HOST=http://127.0.0.1:7091
|
||||
VITE_API_STREAMING=true
|
||||
VITE_NOTIFICATION_TEXT="What's new in 0.15.0 — Changelog"
|
||||
VITE_NOTIFICATION_LINK="https://blog.docsgpt.cloud/docsgpt-0-15-masters-long-term-memory-and-tooling/"
|
||||
VITE_NOTIFICATION_LINK="https://blog.docsgpt.cloud/docsgpt-0-15-masters-long-term-memory-and-tooling/"
|
||||
VITE_GOOGLE_CLIENT_ID=896376503572-u46l78n8ctgtdr4dlei4u06jv6rbpqc5.apps.googleusercontent.com
|
||||
Reference in new issue
Block a user