Skip to content

Commit 30dbfb6

Browse files
authored
Add ability to attach documents to a chat session in all UIs (#327)
1 parent b4a5004 commit 30dbfb6

File tree

28 files changed

+1452
-109
lines changed

28 files changed

+1452
-109
lines changed

.copilot/instructions.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# GLOBAL COPILOT CLI RULES (MANDATORY)
2+
3+
## SOURCE CONTROL RULES
4+
- NEVER run git commit
5+
- NEVER run git push
6+
- NEVER amend commits
7+
- NEVER stage files unless explicitly instructed
8+
- ALL changes must remain local and uncommitted
9+
- Assume the user will manually review and commit
10+
11+
## CODE CHANGE RULES
12+
- You MAY modify files locally
13+
- You MUST clearly describe all changes made
14+
- You MUST assume the user will review diffs before committing
15+
- If unsure, prefer minimal and incremental changes
16+
17+
## DOCUMENTATION ENFORCEMENT (REQUIRED)
18+
Whenever code is modified:
19+
20+
1. You MUST evaluate the documentation project located at:
21+
src\CrestApps.OrchardCore.Documentations
22+
23+
2. You MUST update documentation to reflect the changes:
24+
- Update the relevant **feature documentation first**
25+
- Ensure accuracy with the latest behavior
26+
- Use concise, developer-facing language
27+
28+
3. After feature docs are updated:
29+
- Add an entry to the **changelog** in the same documentation project
30+
- Clearly describe:
31+
- What changed
32+
- Why it changed
33+
- Any breaking or behavioral impact
34+
35+
4. Documentation changes are NOT optional
36+
- Code changes without documentation updates are considered incomplete
37+
38+
## QUALITY EXPECTATIONS
39+
- Prefer clarity over cleverness
40+
- Follow existing project conventions
41+
- Do not introduce undocumented behavior
42+
- Keep documentation and code in sync at all times
43+
44+
## ASSUMPTIONS
45+
- The user evaluates all changes before committing
46+
- The user controls all source control actions

src/Abstractions/CrestApps.OrchardCore.AI.Abstractions/Models/AIChatSession.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ public sealed class AIChatSession : Entity
4141
/// </summary>
4242
public string ClientId { get; set; }
4343

44+
/// <summary>
45+
/// Gets or sets the collection of document references attached to this session.
46+
/// Documents are uploaded by users and used for RAG (Retrieval-Augmented Generation).
47+
/// </summary>
48+
public IList<ChatInteractionDocumentInfo> Documents { get; set; } = [];
49+
4450
/// <summary>
4551
/// Gets or sets the UTC date and time when the session was first created.
4652
/// This property helps track the start time of the session in a standardized format (UTC).

src/Core/CrestApps.OrchardCore.AI.Core/AIConstants.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ public static class AIConstants
1212

1313
public const string DefaultBlankMessage = "AI drew blank and no message was generated!";
1414

15+
public const string DefaultBlankSessionTitle = "Untitled";
16+
1517
public const string CollectionName = "AI";
1618

1719
public const string ConnectionProtectorName = "AIProviderConnection";
@@ -50,6 +52,8 @@ public static class Feature
5052
public const string ProfileDocuments = "CrestApps.OrchardCore.AI.Documents.Profiles";
5153

5254
public const string ChatAdminWidget = "CrestApps.OrchardCore.AI.Chat.AdminWidget";
55+
56+
public const string ChatSessionDocuments = "CrestApps.OrchardCore.AI.Documents.ChatSessions";
5357
}
5458

5559
public static readonly string AIDocumentsIndexingTaskType = "AIDocuments";
@@ -59,6 +63,8 @@ public static class DocumentReferenceTypes
5963
public const string Profile = "profile";
6064

6165
public const string ChatInteraction = "chat-interaction";
66+
67+
public const string ChatSession = "chat-session";
6268
}
6369

6470
public static class ColumnNames
@@ -95,5 +101,9 @@ public static class RouteNames
95101
public const string ChatInteractionUploadDocument = "ChatInteractionUploadDocument";
96102

97103
public const string ChatInteractionRemoveDocument = "ChatInteractionRemoveDocument";
104+
105+
public const string ChatSessionUploadDocument = "ChatSessionUploadDocument";
106+
107+
public const string ChatSessionRemoveDocument = "ChatSessionRemoveDocument";
98108
}
99109
}

src/Core/CrestApps.OrchardCore.AI.Core/Handlers/DocumentOrchestrationHandler.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,19 @@ public Task BuildingAsync(OrchestrationContextBuildingContext context)
4848

4949
public Task BuiltAsync(OrchestrationContextBuiltContext context)
5050
{
51+
// Check for session documents after configure has run,
52+
// since the session is set via the configure callback
53+
// which executes between BuildingAsync and BuiltAsync.
54+
if (context.Context.Documents is not { Count: > 0 } &&
55+
context.Resource is AIProfile &&
56+
context.Context.CompletionContext?.AdditionalProperties is not null &&
57+
context.Context.CompletionContext.AdditionalProperties.TryGetValue("Session", out var sessionObj) &&
58+
sessionObj is AIChatSession session &&
59+
session.Documents is { Count: > 0 })
60+
{
61+
context.Context.Documents = session.Documents;
62+
}
63+
5164
if (context.Context.Documents is not { Count: > 0 } ||
5265
context.Context.CompletionContext is null)
5366
{
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace CrestApps.OrchardCore.AI.Models;
2+
3+
/// <summary>
4+
/// Metadata stored on <see cref="AIProfile.Properties"/> to control
5+
/// whether users can upload documents within AI Chat Sessions.
6+
/// </summary>
7+
public sealed class AIProfileSessionDocumentsMetadata
8+
{
9+
/// <summary>
10+
/// Gets or sets whether users are allowed to upload and attach documents
11+
/// to chat sessions that use this profile.
12+
/// </summary>
13+
public bool AllowSessionDocuments { get; set; }
14+
}

src/CrestApps.OrchardCore.Documentations/docs/ai/documents/index.md

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
sidebar_label: Overview
33
sidebar_position: 1
44
title: AI Documents
5-
description: Document upload, text extraction, embedding, and RAG capabilities for AI Chat Interactions and AI Profiles.
5+
description: Document upload, text extraction, embedding, and RAG capabilities for AI Chat Interactions, AI Profiles, and AI Chat Sessions.
66
---
77

88
| | |
@@ -34,6 +34,7 @@ The base feature (`CrestApps.OrchardCore.AI.Documents`) provides the shared infr
3434
|---------|-----|-------------|
3535
| **AI Documents for Chat Interactions** | `CrestApps.OrchardCore.AI.Documents.ChatInteractions` | Provides document upload and Retrieval-Augmented Generation (RAG) support for AI Chat Interactions. |
3636
| **AI Documents for Profiles** | `CrestApps.OrchardCore.AI.Documents.Profiles` | Provides document upload and Retrieval-Augmented Generation (RAG) support for AI Profiles. |
37+
| **AI Documents for Chat Sessions** | `CrestApps.OrchardCore.AI.Documents.ChatSessions` | Provides document upload and RAG support for AI Chat Sessions and AI Chat Widgets. |
3738

3839
## AI Documents for Chat Interactions
3940

@@ -70,13 +71,6 @@ The orchestrator supports various document-related operations:
7071
- **Content Transformation** — Provides content for reformatting or conversion
7172
- **General Reference** — Provides context when asking general questions that reference documents
7273

73-
### API Endpoints
74-
75-
| Endpoint | Method | Description |
76-
|----------|--------|-------------|
77-
| `/ai/chat-interactions/upload-document` | POST | Upload one or more documents to a chat interaction |
78-
| `/ai/chat-interactions/remove-document` | POST | Remove a document from a chat interaction |
79-
8074
### Getting Started
8175

8276
1. **Set up an indexing provider**: Enable Elasticsearch or Azure AI Search in the Orchard Core admin.
@@ -142,6 +136,56 @@ There are no separate API endpoints for profile document management — everythi
142136
3. Use the **Documents** tab to upload text-based documents.
143137
4. Configure the **Top N Results** setting to control how many matching chunks are included as context.
144138

139+
## AI Documents for Chat Sessions
140+
141+
| | |
142+
| --- | --- |
143+
| **Feature Name** | AI Documents for Chat Sessions |
144+
| **Feature ID** | `CrestApps.OrchardCore.AI.Documents.ChatSessions` |
145+
146+
Provides document upload and Retrieval-Augmented Generation (RAG) support directly within AI Chat Sessions and AI Chat Widgets (both admin and frontend).
147+
148+
When enabled, users can attach documents to any chat session via drag-and-drop or file browser. Documents are indexed using the same shared infrastructure (text extraction, chunking, embedding, and vector search) used by Chat Interactions and Profiles.
149+
150+
Unlike profile documents (which persist across all sessions), chat session documents are **scoped to the individual session** — similar to chat interaction documents.
151+
152+
### Key Capabilities
153+
154+
- **Document Upload**: Drag-and-drop or browse to attach files directly in the chat input area
155+
- **Visual Attach Button**: A persistent "Attach files" button appears above the chat input when enabled
156+
- **Document Pills**: Attached documents are shown as compact pill badges with remove (X) buttons
157+
- **Drag-and-Drop Highlight**: The input area highlights when files are dragged over it
158+
- **Text Extraction & Embedding**: Uploaded documents are automatically extracted, chunked, and embedded for vector search
159+
- **RAG Integration**: Relevant chunks are retrieved and used as context for AI responses
160+
- **Per-Profile Opt-In**: Each AI Profile has an **Allow Documents & Attachments** checkbox (unchecked by default) to control whether document upload is available
161+
162+
### Per-Profile Opt-In
163+
164+
Because document processing is resource-intensive, document upload is **not enabled by default** even when the feature is active. Administrators must explicitly opt in for each AI Profile:
165+
166+
1. Navigate to **Artificial Intelligence > AI Profiles** and edit a profile.
167+
2. In the **Documents** section, check **Allow Documents & Attachments**.
168+
3. Save the profile.
169+
170+
For **AI Chat Widget** content items, the same checkbox appears on the widget editor under the AI profile part settings.
171+
172+
### Supported UIs
173+
174+
| UI | Where | Notes |
175+
|----|-------|-------|
176+
| **AI Chat Session** | Admin > Artificial Intelligence > AI Chat | Full session page |
177+
| **AI Chat Admin Widget** | Floating admin widget | Compact chat widget on admin pages |
178+
| **AI Chat Widget** | Frontend content widget | Public-facing chat widget |
179+
180+
### Getting Started
181+
182+
1. **Set up an indexing provider**: Enable Elasticsearch or Azure AI Search in the Orchard Core admin.
183+
2. **Create an index**: Navigate to **Search > Indexing** and create a new index (e.g., "ChatDocuments").
184+
3. **Configure settings**: Navigate to **Settings > Chat Interaction** and select your new index.
185+
4. **Enable the feature**: Enable `AI Documents for Chat Sessions` in the admin dashboard.
186+
5. **Opt in per profile**: Edit the desired AI Profile and check **Allow Documents & Attachments**.
187+
6. Open a chat session — the attach button and drag-and-drop zone are now available.
188+
145189
## Supported Document Formats
146190

147191
| Format | Extension | Notes |

src/Modules/CrestApps.OrchardCore.AI.Chat/Assets/css/ai-chat-widget.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,3 +390,16 @@
390390
max-height: calc(100vh - 5rem);
391391
}
392392
}
393+
394+
/* Document attachment bar */
395+
.ai-admin-widget .ai-chat-doc-bar {
396+
border-bottom: 1px solid var(--bs-border-color, #dee2e6);
397+
font-size: 0.8rem;
398+
}
399+
400+
/* Drag-over highlight for the widget input area */
401+
.ai-admin-widget-input.ai-chat-drag-over {
402+
outline: 2px dashed var(--ai-widget-primary, #41b670) !important;
403+
outline-offset: -2px;
404+
background-color: rgba(65, 182, 112, 0.05) !important;
405+
}

src/Modules/CrestApps.OrchardCore.AI.Chat/Assets/css/ai-chat.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,15 @@
9292
.ai-chat-messages pre code.hljs {
9393
border-radius: 0.375rem;
9494
}
95+
96+
/* Document attachment bar */
97+
.ai-chat-doc-bar {
98+
border-bottom: 1px solid var(--bs-border-color, #dee2e6);
99+
}
100+
101+
/* Drag-over highlight for the input area */
102+
.ai-chat-drag-over {
103+
outline: 2px dashed var(--bs-primary, #0d6efd) !important;
104+
outline-offset: -2px;
105+
background-color: rgba(13, 110, 253, 0.05) !important;
106+
}

0 commit comments

Comments
 (0)