mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 21:27:20 +00:00
feat(server): edit tool intent collect (#12998)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Footnotes are now included in streamed AI responses, formatted as markdown and appended at the end of the output when available. * **Improvements** * Enhanced handling of footnotes across multiple AI providers, ensuring consistent display of additional information after the main response. * **Refactor** * Removed citation parsing from one provider to streamline output. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -108,6 +108,12 @@ export abstract class AnthropicProvider<T> extends CopilotProvider<T> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!options.signal?.aborted) {
|
||||
const footnotes = parser.end();
|
||||
if (footnotes.length) {
|
||||
yield `\n\n${footnotes}`;
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
metrics.ai.counter('chat_text_stream_errors').add(1, { model: model.id });
|
||||
throw this.handleError(e);
|
||||
|
||||
@@ -166,6 +166,12 @@ export abstract class GeminiProvider<T> extends CopilotProvider<T> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!options.signal?.aborted) {
|
||||
const footnotes = parser.end();
|
||||
if (footnotes.length) {
|
||||
yield `\n\n${footnotes}`;
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
metrics.ai.counter('chat_text_stream_errors').add(1, { model: model.id });
|
||||
throw this.handleError(e);
|
||||
|
||||
@@ -16,7 +16,7 @@ import type {
|
||||
PromptMessage,
|
||||
} from './types';
|
||||
import { CopilotProviderType, ModelInputType, ModelOutputType } from './types';
|
||||
import { chatToGPTMessage, CitationParser, TextStreamParser } from './utils';
|
||||
import { chatToGPTMessage, TextStreamParser } from './utils';
|
||||
|
||||
export const DEFAULT_DIMENSIONS = 256;
|
||||
|
||||
@@ -130,18 +130,11 @@ export class MorphProvider extends CopilotProvider<MorphConfig> {
|
||||
abortSignal: options.signal,
|
||||
});
|
||||
|
||||
const citationParser = new CitationParser();
|
||||
const textParser = new TextStreamParser();
|
||||
for await (const chunk of fullStream) {
|
||||
switch (chunk.type) {
|
||||
case 'text-delta': {
|
||||
let result = textParser.parse(chunk);
|
||||
result = citationParser.parse(result);
|
||||
yield result;
|
||||
break;
|
||||
}
|
||||
case 'finish': {
|
||||
const result = citationParser.end();
|
||||
yield result;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -347,7 +347,9 @@ export class OpenAIProvider extends CopilotProvider<OpenAIConfig> {
|
||||
break;
|
||||
}
|
||||
case 'finish': {
|
||||
const result = citationParser.end();
|
||||
const footnotes = textParser.end();
|
||||
const result =
|
||||
citationParser.end() + (footnotes.length ? '\n' + footnotes : '');
|
||||
yield result;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -412,6 +412,10 @@ export function toError(error: unknown): Error {
|
||||
}
|
||||
}
|
||||
|
||||
type DocEditFootnote = {
|
||||
intent: string;
|
||||
result: string;
|
||||
};
|
||||
export class TextStreamParser {
|
||||
private readonly logger = new Logger(TextStreamParser.name);
|
||||
private readonly CALLOUT_PREFIX = '\n[!]\n';
|
||||
@@ -420,6 +424,8 @@ export class TextStreamParser {
|
||||
|
||||
private prefix: string | null = this.CALLOUT_PREFIX;
|
||||
|
||||
private readonly docEditFootnotes: DocEditFootnote[] = [];
|
||||
|
||||
public parse(chunk: TextStreamPart<CustomAITools>) {
|
||||
let result = '';
|
||||
switch (chunk.type) {
|
||||
@@ -463,6 +469,13 @@ export class TextStreamParser {
|
||||
result += `\nWriting document "${chunk.args.title}"\n`;
|
||||
break;
|
||||
}
|
||||
case 'doc_edit': {
|
||||
this.docEditFootnotes.push({
|
||||
intent: chunk.args.instructions,
|
||||
result: '',
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = this.markAsCallout(result);
|
||||
break;
|
||||
@@ -476,6 +489,10 @@ export class TextStreamParser {
|
||||
case 'doc_edit': {
|
||||
if (chunk.result && typeof chunk.result === 'object') {
|
||||
result += `\n${chunk.result.result}\n`;
|
||||
this.docEditFootnotes[this.docEditFootnotes.length - 1].result =
|
||||
chunk.result.result;
|
||||
} else {
|
||||
this.docEditFootnotes.pop();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -520,6 +537,13 @@ export class TextStreamParser {
|
||||
return result;
|
||||
}
|
||||
|
||||
public end() {
|
||||
const footnotes = this.docEditFootnotes.map((footnote, index) => {
|
||||
return `[^edit${index + 1}]: ${JSON.stringify({ type: 'doc-edit', ...footnote })}`;
|
||||
});
|
||||
return footnotes.join('\n');
|
||||
}
|
||||
|
||||
private addPrefix(text: string) {
|
||||
if (this.prefix) {
|
||||
const result = this.prefix + text;
|
||||
|
||||
Reference in New Issue
Block a user