Skip to content

Commit f065790

Browse files
authored
feat(docs): Add Ask AI error documentation (#2726)
* feat(docs): Add Ask AI error documentation * feat(askai): Render AI stream error messages as Markdown to allow for links
1 parent ba1573f commit f065790

File tree

5 files changed

+102
-24
lines changed

5 files changed

+102
-24
lines changed

packages/docsearch-css/src/modal.css

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -928,7 +928,7 @@ assistive tech users */
928928
.DocSearch-AskAiScreen-Error {
929929
padding: var(--docsearch-spacing);
930930
display: flex;
931-
align-items: center;
931+
align-items: baseline;
932932
padding: 1em;
933933
gap: 8px;
934934
color: var(--docsearch-error-color);
@@ -941,12 +941,17 @@ assistive tech users */
941941
.DocSearch-AskAiScreen-Error svg {
942942
width: 16px;
943943
height: 16px;
944+
flex-shrink: 0;
944945
}
945946

946947
.DocSearch-AskAiScreen-Error p {
947948
margin: 0;
948949
}
949950

951+
.DocSearch-AskAiScreen-Error .DocSearch-Markdown-Content {
952+
color: var(--docsearch-error-color);
953+
}
954+
950955
.DocSearch-AskAiScreen-FeedbackText {
951956
font-size: 0.7em;
952957
font-weight: 400;

packages/docsearch-react/src/AskAiScreen.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,12 @@ function AskAiExchangeCard({
112112
{loadingStatus === 'error' && askAiStreamError && isLastExchange && (
113113
<div className="DocSearch-AskAiScreen-MessageContent DocSearch-AskAiScreen-Error">
114114
<AlertIcon />
115-
<p>{askAiStreamError.message}</p>
115+
<MemoizedMarkdown
116+
content={askAiStreamError.message}
117+
copyButtonText=""
118+
copyButtonCopiedText=""
119+
isStreaming={false}
120+
/>
116121
</div>
117122
)}
118123
{loadingStatus === 'submitted' && isLastExchange && (

packages/website/docs/v4/askai-api.mdx

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,15 @@ Search parameters allow you to control how Ask AI searches your index:
114114
"id": "conversation-1",
115115
"messages": [
116116
{
117-
"role": "user",
117+
"role": "user",
118118
"content": "How do I configure the API?",
119119
"id": "msg-1"
120120
}
121121
],
122122
"searchParameters": {
123123
"facetFilters": [
124124
"language:en",
125-
"version:latest",
125+
"version:latest",
126126
"type:content"
127127
]
128128
}
@@ -158,7 +158,7 @@ This example filters to:
158158
- **Multiple tags**: `[["tag:api", "tag:tutorial"]]` for OR logic
159159
- **Categories with fallbacks**: `[["category:advanced", "category:intermediate"]]`
160160

161-
**Response:**
161+
**Response:**
162162
- **Content-Type:** `text/event-stream`
163163
- **Format:** Server-sent events with incremental AI response chunks
164164
- **Benefits:** Real-time response display, better user experience, lower perceived latency
@@ -173,7 +173,7 @@ const decoder = new TextDecoder();
173173
while (true) {
174174
const { done, value } = await reader.read();
175175
if (done) break;
176-
176+
177177
const chunk = decoder.decode(value);
178178
// Display chunk immediately in your UI
179179
console.log('Received chunk:', chunk);
@@ -250,7 +250,7 @@ class AskAIChat {
250250

251251
async sendMessage(conversationId, messages, searchParameters = {}) {
252252
const token = await this.getToken();
253-
253+
254254
const response = await fetch(`${this.baseUrl}/chat`, {
255255
method: 'POST',
256256
headers: {
@@ -277,12 +277,12 @@ class AskAIChat {
277277
async *[Symbol.asyncIterator]() {
278278
const reader = response.body.getReader();
279279
const decoder = new TextDecoder();
280-
280+
281281
try {
282282
while (true) {
283283
const { done, value } = await reader.read();
284284
if (done) break;
285-
285+
286286
// Decode and yield each chunk as it arrives
287287
const chunk = decoder.decode(value, { stream: true });
288288
if (chunk.trim()) {
@@ -298,7 +298,7 @@ class AskAIChat {
298298

299299
async submitFeedback(messageId, thumbs) {
300300
const token = await this.getToken();
301-
301+
302302
const response = await fetch(`${this.baseUrl}/chat/feedback`, {
303303
method: 'POST',
304304
headers: {
@@ -428,15 +428,15 @@ function AskAIChat({ appId, apiKey, indexName, assistantId }) {
428428
while (true) {
429429
const { done, value } = await reader.read();
430430
if (done) break;
431-
431+
432432
// Decode chunk and add to message
433433
const chunk = decoder.decode(value, { stream: true });
434434
if (chunk.trim()) {
435435
assistantMessage += chunk;
436-
436+
437437
// Update UI with streaming content immediately
438-
setMessages(prev => prev.map(msg =>
439-
msg.id === assistantMessageId
438+
setMessages(prev => prev.map(msg =>
439+
msg.id === assistantMessageId
440440
? { ...msg, content: assistantMessage }
441441
: msg
442442
));
@@ -470,7 +470,7 @@ function AskAIChat({ appId, apiKey, indexName, assistantId }) {
470470
<div className="messages">
471471
{messages.map((message) => (
472472
<div key={message.id} className={`message ${message.role}`}>
473-
<strong>{message.role}:</strong>
473+
<strong>{message.role}:</strong>
474474
<span className={isStreaming && message.role === 'assistant' && message === messages[messages.length - 1] ? 'streaming' : ''}>
475475
{message.content}
476476
{isStreaming && message.role === 'assistant' && message === messages[messages.length - 1] && (
@@ -480,20 +480,20 @@ function AskAIChat({ appId, apiKey, indexName, assistantId }) {
480480
</div>
481481
))}
482482
</div>
483-
483+
484484
<form onSubmit={(e) => {
485485
e.preventDefault();
486486
if (isLoading) return;
487-
487+
488488
const input = e.target.elements.message;
489489
if (input.value.trim()) {
490490
sendMessage(input.value);
491491
input.value = '';
492492
}
493493
}}>
494-
<input
495-
name="message"
496-
type="text"
494+
<input
495+
name="message"
496+
type="text"
497497
placeholder="Ask a question..."
498498
disabled={isLoading}
499499
/>
@@ -594,7 +594,7 @@ async function getToken(assistantId: string, origin: string) {
594594
'Origin': origin,
595595
},
596596
});
597-
597+
598598
const tokenData = await tokenRes.json();
599599
if (!tokenData.success) {
600600
throw new Error(tokenData.message || 'Failed to get token');
@@ -607,7 +607,7 @@ export default async function handler(req: Request) {
607607
const body = await req.json();
608608
const assistantId = process.env.ALGOLIA_ASSISTANT_ID!;
609609
const origin = req.headers.get('origin') || '';
610-
610+
611611
// Fetch a new token before each chat call
612612
const token = await getToken(assistantId, origin);
613613

@@ -637,7 +637,7 @@ export default async function handler(req: Request) {
637637
} catch (error) {
638638
console.error('Chat API error:', error);
639639
return new Response(
640-
JSON.stringify({ error: 'Internal server error' }),
640+
JSON.stringify({ error: 'Internal server error' }),
641641
{ status: 500, headers: { 'Content-Type': 'application/json' } }
642642
);
643643
}
@@ -721,6 +721,8 @@ Common error scenarios:
721721
- **Rate limiting**: Too many requests
722722
- **Invalid index**: Index name doesn't exist or isn't accessible
723723

724+
> Please view our full [Error Reference](/docs/v4/askai-errors.mdx) for more detailed information
725+
724726
---
725727

726728
## Best Practices
@@ -731,4 +733,4 @@ Common error scenarios:
731733
4. **Feedback**: Implement thumbs up/down for continuous improvement
732734
5. **CORS**: Ensure your domain is whitelisted in your Ask AI configuration
733735

734-
For more information, see the [Ask AI documentation](/docs/v4/askai.mdx).
736+
For more information, see the [Ask AI documentation](/docs/v4/askai.mdx).
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
title: Ask AI Errors Reference
3+
---
4+
5+
This is a reference to error codes and their definitions that can be returned from the Ask AI Chat.
6+
7+
## General API errors
8+
9+
---
10+
11+
### UNAUTHORIZED
12+
13+
There was an issue validating the auth token for the request.
14+
15+
### FORBIDDEN
16+
17+
Access to a resources is not available or not allowed for the requester.
18+
19+
> **Solution:** Make sure that your domain is [white listed](/docs/v4/askai-whitelisted-domains) and that you are using the correct `assistantId`.
20+
21+
### BAD_INPUT
22+
23+
The request included data that could either not be used to find a resource, or the data was malformed.
24+
25+
### TOO_MANY_ATTEMPTS
26+
27+
There have been too many requets made within a designated window. The requests are being rate limitted.
28+
29+
> **Solution:** Wait a bit of time for the rate limit window to pass and then try again.
30+
31+
## Ask AI chat errors
32+
33+
---
34+
35+
### AI_STREAM_ERROR
36+
37+
A general case error that occured while from communicating with the upstream provider. This could include stream procesing issues, data corruption, issues with the provider itself and so on.
38+
39+
### AI_API_CALL
40+
41+
There was an issue specifically with communicating with the upstream provider.
42+
43+
> **Solution:** Check the provider's API status pages(s) to see if they are experiencing any ongoing issues.
44+
45+
### AI_INVALID_API_KEY
46+
47+
The upstream provider reported that there was an issue with the supplied API key.
48+
49+
> **Solution:** Make sure to double check that you are using the correct API key for your assistant; and that it has the correct permissions.
50+
51+
### AI_INSUFFICIENT_BALANCE
52+
53+
The upstream provider could not process the chat request to due a billing issue.
54+
55+
> **Solution:** You will need to log into to your provider's dashboard to remedy this issue.
56+
57+
### AI_NO_TOOL
58+
59+
Ask AI could not call a specific tool.
60+
61+
> **Solution:** Be sure to not ask for any specific tool calls within your custom prompt. Ask AI has specific tools it uses to give the best results.
62+
63+
### AI_RETRY
64+
65+
There were too many failed attempts at communicating with the upstream provider. This could be an issue on the provider's end, an issue with the supplied API key or an underlying network issue causing these retries.

packages/website/sidebars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export default {
3131
'v4/askai-whitelisted-domains',
3232
'v4/askai-models',
3333
'v4/askai-markdown-indexing',
34+
'v4/askai-errors',
3435
],
3536
},
3637
{

0 commit comments

Comments
 (0)