Skip to content

Commit 0356c36

Browse files
authored
add RAG sample (Azure#47736)
1 parent 3cbc247 commit 0356c36

File tree

27 files changed

+1052
-0
lines changed

27 files changed

+1052
-0
lines changed

sdk/cloudmachine/Azure.CloudMachine/samples/RAGMachine/.gitignore

Lines changed: 402 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
@page
2+
@model ErrorModel
3+
@{
4+
ViewData["Title"] = "Error";
5+
}
6+
7+
<h1 class="text-danger">Error.</h1>
8+
<h2 class="text-danger">An error occurred while processing your request.</h2>
9+
10+
@if (Model.ShowRequestId)
11+
{
12+
<p>
13+
<strong>Request ID:</strong> <code>@Model.RequestId</code>
14+
</p>
15+
}
16+
17+
<h3>Development Mode</h3>
18+
<p>
19+
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
20+
</p>
21+
<p>
22+
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
23+
It can result in displaying sensitive information from exceptions to end users.
24+
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
25+
and restarting the app.
26+
</p>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Diagnostics;
2+
using Microsoft.AspNetCore.Mvc;
3+
using Microsoft.AspNetCore.Mvc.RazorPages;
4+
5+
namespace RAGMachine.Pages;
6+
7+
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
8+
[IgnoreAntiforgeryToken]
9+
public class ErrorModel : PageModel
10+
{
11+
public string? RequestId { get; set; }
12+
13+
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
14+
15+
private readonly ILogger<ErrorModel> _logger;
16+
17+
public ErrorModel(ILogger<ErrorModel> logger)
18+
{
19+
_logger = logger;
20+
}
21+
22+
public void OnGet()
23+
{
24+
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
25+
}
26+
}
27+
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
@page
2+
@model IndexModel
3+
@{
4+
ViewData["Title"] = "Home page";
5+
}
6+
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
7+
<div class="row justify-content-end">
8+
<p>
9+
<div class="collapse col-5 me-3" id="collapseExample">
10+
<div class="card card-body">
11+
<form id="fileUploadForm" method="post" enctype="multipart/form-data">
12+
<div class="form-group">
13+
<label for="file" class="fw-normal">Upload file:</label>
14+
<input type="file" id="file" name="file" class="form-control-file" />
15+
</div>
16+
</form>
17+
<div id="liveAlertPlaceholder"></div>
18+
</div>
19+
</div>
20+
</p>
21+
</div>
22+
23+
<div class="container mt-5">
24+
<div class="row justify-content-center mt-4">
25+
<span class="text-center fs-1 col-4">Ask Your Data</span>
26+
</div>
27+
<div class="row justify-content-center mt-4">
28+
<div class="col-md-8">
29+
<div id="chatHistory" class="border p-3 mb-3" style="height: 600px; overflow-y: scroll;">
30+
@* Chat history will be appended here *@
31+
</div>
32+
<div class="input-group mb-3">
33+
<button class="btn btn-outline-secondary" type="button" id="filebtn">
34+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M9 7C9 4.23858 11.2386 2 14 2C16.7614 2 19 4.23858 19 7V15C19 18.866 15.866 22 12 22C8.13401 22 5 18.866 5 15V9C5 8.44772 5.44772 8 6 8C6.55228 8 7 8.44772 7 9V15C7 17.7614 9.23858 20 12 20C14.7614 20 17 17.7614 17 15V7C17 5.34315 15.6569 4 14 4C12.3431 4 11 5.34315 11 7V15C11 15.5523 11.4477 16 12 16C12.5523 16 13 15.5523 13 15V9C13 8.44772 13.4477 8 14 8C14.5523 8 15 8.44772 15 9V15C15 16.6569 13.6569 18 12 18C10.3431 18 9 16.6569 9 15V7Z" fill="currentColor"></path></svg>
35+
</button>
36+
<input type="text" id="chatPrompt2" class="form-control" aria-label="chat" placeholder="Type your prompt here...">
37+
<button class="btn btn-outline-secondary" type="button" id="sendPrompt2">
38+
<svg width="32" height="32" viewBox="0 0 32 32" fill="white" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.1918 8.90615C15.6381 8.45983 16.3618 8.45983 16.8081 8.90615L21.9509 14.049C22.3972 14.4953 22.3972 15.2189 21.9509 15.6652C21.5046 16.1116 20.781 16.1116 20.3347 15.6652L17.1428 12.4734V22.2857C17.1428 22.9169 16.6311 23.4286 15.9999 23.4286C15.3688 23.4286 14.8571 22.9169 14.8571 22.2857V12.4734L11.6652 15.6652C11.2189 16.1116 10.4953 16.1116 10.049 15.6652C9.60265 15.2189 9.60265 14.4953 10.049 14.049L15.1918 8.90615Z" fill="white"></path></svg>
39+
</button>
40+
</div>
41+
</div>
42+
</div>
43+
</div>
44+
45+
<script>
46+
$(document).ready(function () {
47+
var allowedExtensions = ['.txt', '.md', '.json'];
48+
49+
$('#sendPrompt2').click(function () {
50+
var prompt = $('#chatPrompt2').val();
51+
if (prompt.trim() === '') {
52+
return;
53+
}
54+
55+
// Clear the chat prompt textbox
56+
$('#chatPrompt2').val('');
57+
58+
// Add the prompt to the chat history
59+
$('#chatHistory').append('<p><strong>You:</strong> ' + prompt + '</p>');
60+
61+
// Send the prompt to the backend via AJAX
62+
$.ajax({
63+
url: '/chat',
64+
type: 'POST',
65+
contentType: 'application/json',
66+
data: prompt,
67+
success: function (response) {
68+
// Add the response to the chat history
69+
$('#chatHistory').append('<p><strong>Agent:</strong> ' + response + '</p>');
70+
// Scroll to the bottom of the chat history
71+
$('#chatHistory').scrollTop($('#chatHistory')[0].scrollHeight);
72+
},
73+
error: function (jqXHR, textStatus, errorThrown) {
74+
// Display an error message in the chat history
75+
$('#chatHistory').append('<p><strong>Agent:</strong> Error occurred while processing your request: ' + jqXHR.responseText + '</p>');
76+
// Scroll to the bottom of the chat history
77+
$('#chatHistory').scrollTop($('#chatHistory')[0].scrollHeight);
78+
}
79+
});
80+
});
81+
82+
$('#filebtn').click(function () {
83+
$('#file').click();
84+
});
85+
86+
$('#file').change(function () {
87+
if ($('#file').val()) {
88+
if (validateFileType()) {
89+
$('#fileUploadForm').submit();
90+
} else {
91+
alert('Unsupported file type. Please select one of the supported file types: ' + allowedExtensions.slice(0, -1).join(', ') + ', and ' + allowedExtensions.slice(-1) + '.');
92+
$('#file').val(''); // Clear the file input
93+
}
94+
}
95+
});
96+
97+
$('#fileUploadForm').submit(function (e) {
98+
e.preventDefault(); // Prevent the default form submission
99+
100+
// var formData = new FormData(this);
101+
var formData = new FormData();
102+
var fileInput = document.getElementById('file');
103+
var file = fileInput.files[0];
104+
105+
// Append the file with a specific content type
106+
formData.append('file', new Blob([file], { type: 'text/plain' }), file.name);
107+
108+
$.ajax({
109+
url: '/upload', // Replace with your actual upload endpoint
110+
type: 'POST',
111+
data: formData,
112+
contentType: false,
113+
processData: false,
114+
success: function (response) {
115+
// Handle success response
116+
appendAlert('File uploaded successfully!', 'success');
117+
const fileList = document.getElementById('fileList');
118+
const wrapper = document.createElement('li');
119+
wrapper.innerHTML = '<a class="dropdown-item" href="#">' + file.name + '</a>';
120+
fileList.append(wrapper);
121+
122+
$('#file').val(''); // Clear the file input
123+
},
124+
error: function (jqXHR, textStatus, errorThrown) {
125+
// Handle error response
126+
alert('Error occurred while uploading the file: ' + jqXHR.responseText);
127+
}
128+
});
129+
});
130+
const alertPlaceholder = document.getElementById('liveAlertPlaceholder');
131+
const appendAlert = (message, type) => {
132+
const wrapper = document.createElement('div');
133+
wrapper.innerHTML = [
134+
`<div class="alert alert-${type} alert-dismissible" role="alert">`,
135+
` <div>${message}</div>`,
136+
' <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>',
137+
'</div>'
138+
].join('')
139+
140+
alertPlaceholder.append(wrapper)
141+
}
142+
143+
// Add keypress event listener to chatPrompt input
144+
$('#chatPrompt2').keypress(function (e) {
145+
if (e.which === 13) { // Enter key pressed
146+
$('#sendPrompt2').click();
147+
return false; // Prevent the default form submission
148+
}
149+
});
150+
151+
// Function to validate the file type
152+
function validateFileType() {
153+
var fileInput = document.getElementById('file');
154+
var filePath = fileInput.value;
155+
var fileExtension = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();
156+
return allowedExtensions.includes(fileExtension);
157+
}
158+
});
159+
</script>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using Microsoft.AspNetCore.Mvc.RazorPages;
3+
4+
namespace RAGMachine.Pages;
5+
6+
public class IndexModel : PageModel
7+
{
8+
private readonly ILogger<IndexModel> _logger;
9+
10+
public IndexModel(ILogger<IndexModel> logger)
11+
{
12+
_logger = logger;
13+
}
14+
15+
public void OnGet()
16+
{
17+
18+
}
19+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@page
2+
@model PrivacyModel
3+
@{
4+
ViewData["Title"] = "Privacy Policy";
5+
}
6+
<h1>@ViewData["Title"]</h1>
7+
8+
<p>Use this page to detail your site's privacy policy.</p>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using Microsoft.AspNetCore.Mvc.RazorPages;
3+
4+
namespace RAGMachine.Pages;
5+
6+
public class PrivacyModel : PageModel
7+
{
8+
private readonly ILogger<PrivacyModel> _logger;
9+
10+
public PrivacyModel(ILogger<PrivacyModel> logger)
11+
{
12+
_logger = logger;
13+
}
14+
15+
public void OnGet()
16+
{
17+
}
18+
}
19+
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<!DOCTYPE html>
2+
<html lang="en" data-bs-theme="dark">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>@ViewData["Title"] - RAGMachine</title>
7+
<script type="importmap"></script>
8+
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
9+
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
10+
<link rel="stylesheet" href="~/RAGMachine.styles.css" asp-append-version="true" />
11+
</head>
12+
<body>
13+
<header>
14+
<nav class="navbar navbar-expand-lg bg-body-tertiary">
15+
<div class="container-fluid">
16+
<a class="navbar-brand" asp-area="" asp-page="/Index">RAGMachine</a>
17+
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
18+
aria-expanded="false" aria-label="Toggle navigation">
19+
<span class="navbar-toggler-icon"></span>
20+
</button>
21+
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
22+
<ul class="navbar-nav flex-grow-1">
23+
<li class="nav-item">
24+
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
25+
</li>
26+
<li class="nav-item dropdown">
27+
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
28+
Files Uploaded
29+
</a>
30+
<ul id="fileList" class="dropdown-menu">
31+
</ul>
32+
</li>
33+
</ul>
34+
</div>
35+
</div>
36+
</nav>
37+
</header>
38+
<div class="container">
39+
<main role="main" class="pb-3">
40+
@RenderBody()
41+
</main>
42+
</div>
43+
44+
<footer class="border-top footer text-muted">
45+
<div class="container">
46+
&copy; 2024 - RAGMachine - <a asp-area="" asp-page="/Privacy">Privacy</a>
47+
</div>
48+
</footer>
49+
50+
<script src="~/lib/jquery/dist/jquery.min.js"></script>
51+
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
52+
<script src="~/js/site.js" asp-append-version="true"></script>
53+
54+
@await RenderSectionAsync("Scripts", required: false)
55+
</body>
56+
</html>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
2+
for details on configuring this project to bundle and minify static web assets. */
3+
4+
a.navbar-brand {
5+
white-space: normal;
6+
text-align: center;
7+
word-break: break-all;
8+
}
9+
10+
/*a {
11+
color: #0077cc;
12+
}*/
13+
14+
.btn-primary {
15+
color: #fff;
16+
background-color: #1b6ec2;
17+
border-color: #1861ac;
18+
}
19+
20+
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
21+
color: #fff;
22+
background-color: #1b6ec2;
23+
border-color: #1861ac;
24+
}
25+
26+
.border-top {
27+
border-top: 1px solid #e5e5e5;
28+
}
29+
.border-bottom {
30+
border-bottom: 1px solid #e5e5e5;
31+
}
32+
33+
.box-shadow {
34+
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
35+
}
36+
37+
button.accept-policy {
38+
font-size: 1rem;
39+
line-height: inherit;
40+
}
41+
42+
.footer {
43+
position: absolute;
44+
bottom: 0;
45+
width: 100%;
46+
white-space: nowrap;
47+
line-height: 60px;
48+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
2+
<script src="~/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js"></script>

0 commit comments

Comments
 (0)