mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-03 02:20:19 +08:00
feat(server): improve context metadata & matching (#12064)
fix AI-20 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Enhanced file metadata with MIME type, blob ID, and file name across context and workspace, now visible in UI and API. - Added workspace-level matching for files and documents with configurable thresholds and workspace scoping in search queries. - Introduced a new error type and user-friendly messaging for global workspace context matching failures. - **Bug Fixes** - Improved consistent handling of file MIME types and nullable context IDs for accurate metadata. - **Documentation** - Updated GraphQL schema, queries, and mutations to include new metadata fields, optional parameters, and error types. - **Style** - Added new localization strings for global context matching error messages. - **Tests** - Extended test coverage with new and updated snapshot tests for metadata and matching logic. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -3,6 +3,7 @@ mutation addContextFile($content: Upload!, $options: AddContextFileInput!) {
|
||||
id
|
||||
createdAt
|
||||
name
|
||||
mimeType
|
||||
chunkSize
|
||||
error
|
||||
status
|
||||
|
||||
@@ -15,6 +15,7 @@ query listContextObject(
|
||||
files {
|
||||
id
|
||||
name
|
||||
mimeType
|
||||
blobId
|
||||
chunkSize
|
||||
error
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
query matchContext($contextId: String!, $content: String!, $limit: SafeInt, $threshold: Float) {
|
||||
query matchContext($contextId: String, $workspaceId: String, $content: String!, $limit: SafeInt, $scopedThreshold: Float, $threshold: Float) {
|
||||
currentUser {
|
||||
copilot {
|
||||
copilot(workspaceId: $workspaceId) {
|
||||
contexts(contextId: $contextId) {
|
||||
matchFiles(content: $content, limit: $limit, threshold: $threshold) {
|
||||
matchFiles(content: $content, limit: $limit, scopedThreshold: $scopedThreshold, threshold: $threshold) {
|
||||
fileId
|
||||
blobId
|
||||
name
|
||||
mimeType
|
||||
chunk
|
||||
content
|
||||
distance
|
||||
}
|
||||
matchWorkspaceDocs(content: $content, limit: $limit, threshold: $threshold) {
|
||||
matchWorkspaceDocs(content: $content, limit: $limit, scopedThreshold: $scopedThreshold, threshold: $threshold) {
|
||||
docId
|
||||
chunk
|
||||
content
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
query matchWorkspaceDocs($contextId: String!, $content: String!, $limit: SafeInt, $scopedThreshold: Float, $threshold: Float) {
|
||||
query matchWorkspaceDocs($contextId: String, $workspaceId: String, $content: String!, $limit: SafeInt, $scopedThreshold: Float, $threshold: Float) {
|
||||
currentUser {
|
||||
copilot {
|
||||
copilot(workspaceId: $workspaceId) {
|
||||
contexts(contextId: $contextId) {
|
||||
matchWorkspaceDocs(content: $content, limit: $limit, scopedThreshold: $scopedThreshold, threshold: $threshold) {
|
||||
docId
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
query matchFiles($contextId: String!, $content: String!, $limit: SafeInt, $threshold: Float) {
|
||||
query matchFiles($contextId: String, $workspaceId: String, $content: String!, $limit: SafeInt, $scopedThreshold: Float, $threshold: Float) {
|
||||
currentUser {
|
||||
copilot {
|
||||
copilot(workspaceId: $workspaceId) {
|
||||
contexts(contextId: $contextId) {
|
||||
matchFiles(content: $content, limit: $limit, threshold: $threshold) {
|
||||
matchFiles(content: $content, limit: $limit, scopedThreshold: $scopedThreshold, threshold: $threshold) {
|
||||
fileId
|
||||
blobId
|
||||
chunk
|
||||
content
|
||||
distance
|
||||
|
||||
@@ -2,6 +2,7 @@ mutation addWorkspaceEmbeddingFiles($workspaceId: String!, $blob: Upload!) {
|
||||
addWorkspaceEmbeddingFiles(workspaceId: $workspaceId, blob: $blob) {
|
||||
fileId
|
||||
fileName
|
||||
blobId
|
||||
mimeType
|
||||
size
|
||||
createdAt
|
||||
|
||||
@@ -11,6 +11,7 @@ query getWorkspaceEmbeddingFiles($workspaceId: String!, $pagination: PaginationI
|
||||
node {
|
||||
fileId
|
||||
fileName
|
||||
blobId
|
||||
mimeType
|
||||
size
|
||||
createdAt
|
||||
|
||||
@@ -390,6 +390,7 @@ export const addContextFileMutation = {
|
||||
id
|
||||
createdAt
|
||||
name
|
||||
mimeType
|
||||
chunkSize
|
||||
error
|
||||
status
|
||||
@@ -423,6 +424,7 @@ export const listContextObjectQuery = {
|
||||
files {
|
||||
id
|
||||
name
|
||||
mimeType
|
||||
blobId
|
||||
chunkSize
|
||||
error
|
||||
@@ -473,17 +475,30 @@ export const listContextQuery = {
|
||||
export const matchContextQuery = {
|
||||
id: 'matchContextQuery' as const,
|
||||
op: 'matchContext',
|
||||
query: `query matchContext($contextId: String!, $content: String!, $limit: SafeInt, $threshold: Float) {
|
||||
query: `query matchContext($contextId: String, $workspaceId: String, $content: String!, $limit: SafeInt, $scopedThreshold: Float, $threshold: Float) {
|
||||
currentUser {
|
||||
copilot {
|
||||
copilot(workspaceId: $workspaceId) {
|
||||
contexts(contextId: $contextId) {
|
||||
matchFiles(content: $content, limit: $limit, threshold: $threshold) {
|
||||
matchFiles(
|
||||
content: $content
|
||||
limit: $limit
|
||||
scopedThreshold: $scopedThreshold
|
||||
threshold: $threshold
|
||||
) {
|
||||
fileId
|
||||
blobId
|
||||
name
|
||||
mimeType
|
||||
chunk
|
||||
content
|
||||
distance
|
||||
}
|
||||
matchWorkspaceDocs(content: $content, limit: $limit, threshold: $threshold) {
|
||||
matchWorkspaceDocs(
|
||||
content: $content
|
||||
limit: $limit
|
||||
scopedThreshold: $scopedThreshold
|
||||
threshold: $threshold
|
||||
) {
|
||||
docId
|
||||
chunk
|
||||
content
|
||||
@@ -498,9 +513,9 @@ export const matchContextQuery = {
|
||||
export const matchWorkspaceDocsQuery = {
|
||||
id: 'matchWorkspaceDocsQuery' as const,
|
||||
op: 'matchWorkspaceDocs',
|
||||
query: `query matchWorkspaceDocs($contextId: String!, $content: String!, $limit: SafeInt, $scopedThreshold: Float, $threshold: Float) {
|
||||
query: `query matchWorkspaceDocs($contextId: String, $workspaceId: String, $content: String!, $limit: SafeInt, $scopedThreshold: Float, $threshold: Float) {
|
||||
currentUser {
|
||||
copilot {
|
||||
copilot(workspaceId: $workspaceId) {
|
||||
contexts(contextId: $contextId) {
|
||||
matchWorkspaceDocs(
|
||||
content: $content
|
||||
@@ -522,12 +537,18 @@ export const matchWorkspaceDocsQuery = {
|
||||
export const matchFilesQuery = {
|
||||
id: 'matchFilesQuery' as const,
|
||||
op: 'matchFiles',
|
||||
query: `query matchFiles($contextId: String!, $content: String!, $limit: SafeInt, $threshold: Float) {
|
||||
query: `query matchFiles($contextId: String, $workspaceId: String, $content: String!, $limit: SafeInt, $scopedThreshold: Float, $threshold: Float) {
|
||||
currentUser {
|
||||
copilot {
|
||||
copilot(workspaceId: $workspaceId) {
|
||||
contexts(contextId: $contextId) {
|
||||
matchFiles(content: $content, limit: $limit, threshold: $threshold) {
|
||||
matchFiles(
|
||||
content: $content
|
||||
limit: $limit
|
||||
scopedThreshold: $scopedThreshold
|
||||
threshold: $threshold
|
||||
) {
|
||||
fileId
|
||||
blobId
|
||||
chunk
|
||||
content
|
||||
distance
|
||||
@@ -750,6 +771,7 @@ export const addWorkspaceEmbeddingFilesMutation = {
|
||||
addWorkspaceEmbeddingFiles(workspaceId: $workspaceId, blob: $blob) {
|
||||
fileId
|
||||
fileName
|
||||
blobId
|
||||
mimeType
|
||||
size
|
||||
createdAt
|
||||
@@ -774,6 +796,7 @@ export const getWorkspaceEmbeddingFilesQuery = {
|
||||
node {
|
||||
fileId
|
||||
fileName
|
||||
blobId
|
||||
mimeType
|
||||
size
|
||||
createdAt
|
||||
|
||||
@@ -109,10 +109,13 @@ export interface ContextMatchedDocChunk {
|
||||
|
||||
export interface ContextMatchedFileChunk {
|
||||
__typename?: 'ContextMatchedFileChunk';
|
||||
blobId: Scalars['String']['output'];
|
||||
chunk: Scalars['SafeInt']['output'];
|
||||
content: Scalars['String']['output'];
|
||||
distance: Maybe<Scalars['Float']['output']>;
|
||||
fileId: Scalars['String']['output'];
|
||||
mimeType: Scalars['String']['output'];
|
||||
name: Scalars['String']['output'];
|
||||
}
|
||||
|
||||
export interface ContextWorkspaceEmbeddingStatus {
|
||||
@@ -172,7 +175,7 @@ export interface CopilotContext {
|
||||
docs: Array<CopilotContextDoc>;
|
||||
/** list files in context */
|
||||
files: Array<CopilotContextFile>;
|
||||
id: Scalars['ID']['output'];
|
||||
id: Maybe<Scalars['ID']['output']>;
|
||||
/** match file in context */
|
||||
matchFiles: Array<ContextMatchedFileChunk>;
|
||||
/** match workspace docs */
|
||||
@@ -185,6 +188,7 @@ export interface CopilotContext {
|
||||
export interface CopilotContextMatchFilesArgs {
|
||||
content: Scalars['String']['input'];
|
||||
limit?: InputMaybe<Scalars['SafeInt']['input']>;
|
||||
scopedThreshold?: InputMaybe<Scalars['Float']['input']>;
|
||||
threshold?: InputMaybe<Scalars['Float']['input']>;
|
||||
}
|
||||
|
||||
@@ -218,6 +222,7 @@ export interface CopilotContextFile {
|
||||
createdAt: Scalars['SafeInt']['output'];
|
||||
error: Maybe<Scalars['String']['output']>;
|
||||
id: Scalars['ID']['output'];
|
||||
mimeType: Scalars['String']['output'];
|
||||
name: Scalars['String']['output'];
|
||||
status: ContextEmbedStatus;
|
||||
}
|
||||
@@ -252,6 +257,13 @@ export interface CopilotFailedToMatchContextDataType {
|
||||
message: Scalars['String']['output'];
|
||||
}
|
||||
|
||||
export interface CopilotFailedToMatchGlobalContextDataType {
|
||||
__typename?: 'CopilotFailedToMatchGlobalContextDataType';
|
||||
content: Scalars['String']['output'];
|
||||
message: Scalars['String']['output'];
|
||||
workspaceId: Scalars['String']['output'];
|
||||
}
|
||||
|
||||
export interface CopilotFailedToModifyContextDataType {
|
||||
__typename?: 'CopilotFailedToModifyContextDataType';
|
||||
contextId: Scalars['String']['output'];
|
||||
@@ -383,6 +395,7 @@ export interface CopilotWorkspaceConfigIgnoredDocsArgs {
|
||||
|
||||
export interface CopilotWorkspaceFile {
|
||||
__typename?: 'CopilotWorkspaceFile';
|
||||
blobId: Scalars['String']['output'];
|
||||
createdAt: Scalars['DateTime']['output'];
|
||||
fileId: Scalars['String']['output'];
|
||||
fileName: Scalars['String']['output'];
|
||||
@@ -582,6 +595,7 @@ export type ErrorDataUnion =
|
||||
| CopilotDocNotFoundDataType
|
||||
| CopilotFailedToAddWorkspaceFileEmbeddingDataType
|
||||
| CopilotFailedToMatchContextDataType
|
||||
| CopilotFailedToMatchGlobalContextDataType
|
||||
| CopilotFailedToModifyContextDataType
|
||||
| CopilotInvalidContextDataType
|
||||
| CopilotMessageNotFoundDataType
|
||||
@@ -651,6 +665,7 @@ export enum ErrorNames {
|
||||
COPILOT_FAILED_TO_CREATE_MESSAGE = 'COPILOT_FAILED_TO_CREATE_MESSAGE',
|
||||
COPILOT_FAILED_TO_GENERATE_TEXT = 'COPILOT_FAILED_TO_GENERATE_TEXT',
|
||||
COPILOT_FAILED_TO_MATCH_CONTEXT = 'COPILOT_FAILED_TO_MATCH_CONTEXT',
|
||||
COPILOT_FAILED_TO_MATCH_GLOBAL_CONTEXT = 'COPILOT_FAILED_TO_MATCH_GLOBAL_CONTEXT',
|
||||
COPILOT_FAILED_TO_MODIFY_CONTEXT = 'COPILOT_FAILED_TO_MODIFY_CONTEXT',
|
||||
COPILOT_INVALID_CONTEXT = 'COPILOT_INVALID_CONTEXT',
|
||||
COPILOT_MESSAGE_NOT_FOUND = 'COPILOT_MESSAGE_NOT_FOUND',
|
||||
@@ -2876,6 +2891,7 @@ export type AddContextFileMutation = {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
name: string;
|
||||
mimeType: string;
|
||||
chunkSize: number;
|
||||
error: string | null;
|
||||
status: ContextEmbedStatus;
|
||||
@@ -2917,6 +2933,7 @@ export type ListContextObjectQuery = {
|
||||
__typename?: 'CopilotContextFile';
|
||||
id: string;
|
||||
name: string;
|
||||
mimeType: string;
|
||||
blobId: string;
|
||||
chunkSize: number;
|
||||
error: string | null;
|
||||
@@ -2965,7 +2982,7 @@ export type ListContextQuery = {
|
||||
__typename?: 'Copilot';
|
||||
contexts: Array<{
|
||||
__typename?: 'CopilotContext';
|
||||
id: string;
|
||||
id: string | null;
|
||||
workspaceId: string;
|
||||
}>;
|
||||
};
|
||||
@@ -2973,9 +2990,11 @@ export type ListContextQuery = {
|
||||
};
|
||||
|
||||
export type MatchContextQueryVariables = Exact<{
|
||||
contextId: Scalars['String']['input'];
|
||||
contextId?: InputMaybe<Scalars['String']['input']>;
|
||||
workspaceId?: InputMaybe<Scalars['String']['input']>;
|
||||
content: Scalars['String']['input'];
|
||||
limit?: InputMaybe<Scalars['SafeInt']['input']>;
|
||||
scopedThreshold?: InputMaybe<Scalars['Float']['input']>;
|
||||
threshold?: InputMaybe<Scalars['Float']['input']>;
|
||||
}>;
|
||||
|
||||
@@ -2990,6 +3009,9 @@ export type MatchContextQuery = {
|
||||
matchFiles: Array<{
|
||||
__typename?: 'ContextMatchedFileChunk';
|
||||
fileId: string;
|
||||
blobId: string;
|
||||
name: string;
|
||||
mimeType: string;
|
||||
chunk: number;
|
||||
content: string;
|
||||
distance: number | null;
|
||||
@@ -3007,7 +3029,8 @@ export type MatchContextQuery = {
|
||||
};
|
||||
|
||||
export type MatchWorkspaceDocsQueryVariables = Exact<{
|
||||
contextId: Scalars['String']['input'];
|
||||
contextId?: InputMaybe<Scalars['String']['input']>;
|
||||
workspaceId?: InputMaybe<Scalars['String']['input']>;
|
||||
content: Scalars['String']['input'];
|
||||
limit?: InputMaybe<Scalars['SafeInt']['input']>;
|
||||
scopedThreshold?: InputMaybe<Scalars['Float']['input']>;
|
||||
@@ -3035,9 +3058,11 @@ export type MatchWorkspaceDocsQuery = {
|
||||
};
|
||||
|
||||
export type MatchFilesQueryVariables = Exact<{
|
||||
contextId: Scalars['String']['input'];
|
||||
contextId?: InputMaybe<Scalars['String']['input']>;
|
||||
workspaceId?: InputMaybe<Scalars['String']['input']>;
|
||||
content: Scalars['String']['input'];
|
||||
limit?: InputMaybe<Scalars['SafeInt']['input']>;
|
||||
scopedThreshold?: InputMaybe<Scalars['Float']['input']>;
|
||||
threshold?: InputMaybe<Scalars['Float']['input']>;
|
||||
}>;
|
||||
|
||||
@@ -3052,6 +3077,7 @@ export type MatchFilesQuery = {
|
||||
matchFiles: Array<{
|
||||
__typename?: 'ContextMatchedFileChunk';
|
||||
fileId: string;
|
||||
blobId: string;
|
||||
chunk: number;
|
||||
content: string;
|
||||
distance: number | null;
|
||||
@@ -3321,6 +3347,7 @@ export type AddWorkspaceEmbeddingFilesMutation = {
|
||||
__typename?: 'CopilotWorkspaceFile';
|
||||
fileId: string;
|
||||
fileName: string;
|
||||
blobId: string;
|
||||
mimeType: string;
|
||||
size: number;
|
||||
createdAt: string;
|
||||
@@ -3352,6 +3379,7 @@ export type GetWorkspaceEmbeddingFilesQuery = {
|
||||
__typename?: 'CopilotWorkspaceFile';
|
||||
fileId: string;
|
||||
fileName: string;
|
||||
blobId: string;
|
||||
mimeType: string;
|
||||
size: number;
|
||||
createdAt: string;
|
||||
|
||||
Reference in New Issue
Block a user