-
Notifications
You must be signed in to change notification settings - Fork 156
/
index.ts
153 lines (128 loc) · 4.85 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Import required packages
import { config } from 'dotenv';
import * as path from 'path';
import * as restify from 'restify';
// Import required bot services.
// See https://aka.ms/bot-services to learn more about the different parts of a bot.
import { ConfigurationServiceClientCredentialFactory, MemoryStorage, TurnContext } from 'botbuilder';
import {
AI,
Application,
ActionPlanner,
OpenAIModel,
PromptManager,
TurnState,
TeamsAdapter
} from '@microsoft/teams-ai';
import { addResponseFormatter } from './responseFormatter';
import { VectraDataSource } from './VectraDataSource';
// Read botFilePath and botFileSecret from .env file.
const ENV_FILE = path.join(__dirname, '..', '.env');
config({ path: ENV_FILE });
// Create adapter.
// See https://aka.ms/about-bot-adapter to learn more about how bots work.
const adapter = new TeamsAdapter(
{},
new ConfigurationServiceClientCredentialFactory({
MicrosoftAppId: process.env.BOT_ID,
MicrosoftAppPassword: process.env.BOT_PASSWORD,
MicrosoftAppType: 'MultiTenant'
})
);
// Catch-all for errors.
const onTurnErrorHandler = async (context: TurnContext, error: any) => {
// This check writes out errors to console log .vs. app insights.
// NOTE: In production environment, you should consider logging this to Azure
// application insights.
console.error(`\n [onTurnError] unhandled error: ${error}`);
console.log(error);
// Send a trace activity, which will be displayed in Bot Framework Emulator
await context.sendTraceActivity(
'OnTurnError Trace',
`${error}`,
'https://www.botframework.com/schemas/error',
'TurnError'
);
// Send a message to the user
await context.sendActivity('The bot encountered an error or bug.');
await context.sendActivity('To continue to run this bot, please fix the bot source code.');
};
// Set the onTurnError for the singleton CloudAdapter.
adapter.onTurnError = onTurnErrorHandler;
// Create HTTP server.
const server = restify.createServer();
server.use(restify.plugins.bodyParser());
server.listen(process.env.port || process.env.PORT || 3978, () => {
console.log(`\n${server.name} listening to ${server.url}`);
console.log('\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator');
console.log('\nTo test your bot in Teams, sideload the app manifest.json within Teams Apps.');
});
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface ConversationState {}
type ApplicationTurnState = TurnState<ConversationState>;
if (!process.env.OPENAI_KEY && !process.env.AZURE_OPENAI_KEY) {
throw new Error('Missing environment variables - please check that OPENAI_KEY or AZURE_OPENAI_KEY is set.');
}
// Create AI components
const model = new OpenAIModel({
// OpenAI Support
apiKey: process.env.OPENAI_KEY!,
defaultModel: 'gpt-3.5-turbo',
// Azure OpenAI Support
azureApiKey: process.env.AZURE_OPENAI_KEY!,
azureDefaultDeployment: 'gpt-3.5-turbo',
azureEndpoint: process.env.AZURE_OPENAI_ENDPOINT!,
azureApiVersion: '2023-03-15-preview',
// Request logging
logRequests: true
});
const prompts = new PromptManager({
promptsFolder: path.join(__dirname, '../src/prompts')
});
const planner = new ActionPlanner({
model,
prompts,
defaultPrompt: 'chat'
});
// Define storage and application
const storage = new MemoryStorage();
const app = new Application<ApplicationTurnState>({
storage,
ai: {
planner
}
});
// Register your data source with planner
planner.prompts.addDataSource(
new VectraDataSource({
name: 'teams-ai',
apiKey: process.env.OPENAI_KEY!,
azureApiKey: process.env.AZURE_OPENAI_KEY!,
azureEndpoint: process.env.AZURE_OPENAI_ENDPOINT!,
indexFolder: path.join(__dirname, '../index')
})
);
// Add a custom response formatter to convert markdown code blocks to <pre> tags
addResponseFormatter(app);
// Register other AI actions
app.ai.action(
AI.FlaggedInputActionName,
async (context: TurnContext, state: ApplicationTurnState, data: Record<string, any>) => {
await context.sendActivity(`I'm sorry your message was flagged: ${JSON.stringify(data)}`);
return AI.StopCommandName;
}
);
app.ai.action(AI.FlaggedOutputActionName, async (context: TurnContext, state: ApplicationTurnState, data: any) => {
await context.sendActivity(`I'm not allowed to talk about such things.`);
return AI.StopCommandName;
});
// Listen for incoming server requests.
server.post('/api/messages', async (req, res) => {
// Route received a request to adapter for processing
await adapter.process(req, res as any, async (context) => {
// Dispatch to application for routing
await app.run(context);
});
});