Статьи

Разговорный пользовательский интерфейс с Oracle Digital Assistant и Fn Project

В этой статье я продолжу рассказ о реализации диалогового пользовательского интерфейса для FlexDeploy поверх Oracle Digital Assistant и
Проект Fn . Сегодня я собираюсь перенести серверный API, работающий вокруг моего чат-бота, в облако, поэтому все решение работает в облаке:

Разговорный интерфейс

API реализован в виде набора функций Fn, собранных в приложении Fn. Прелесть Fn в том, что это просто набор контейнеров Docker, которые могут одинаково работать на вашем ноутбуке на вашем локальном движке Docker и где-то в облаке. Сказав, что я могу запустить свое приложение Fn в кластере K8s от любого облачного провайдера, как описано здесь . Но сегодня не тот день. Сегодня я собираюсь запустить свой серверный API на новом облачном сервисе Oracle Functions, который построен на основе Fn. Услуга еще не является общедоступной, но я участвую в программе ограниченной доступности, поэтому у меня есть пробный доступ к ней, я могу поиграть с ней и написать об этом в блоге. В этом решении мне пришлось избавиться от реализованного здесь Fn Flow и вернуться к моей первоначальной реализации, поскольку Fn Flow еще не поддерживается функциями Oracle. Я надеюсь, что это будет скоро, поскольку это — действительно лучшая часть.

Итак, настроив нашу среду OCI и запустив службу Oracle Functions (я здесь не репостирую руководство по Oracle), нам нужно настроить CLI Fn для связи с сервисом:

1
2
3
4
5
6
fn create context oracle_fn --provider oracle
fn use context oracle_fn
fn update context oracle.compartment-id MY_COMPARTMENT_ID
fn update context api-url https://functions.us-phoenix-1.oraclecloud.com
fn update context registry phx.ocir.io/flexagonoraclecloud/flexagon-repo
fn update context oracle.profile oracle_fn

Итак, теперь наш интерфейс командной строки Fn общается с функциями Oracle . Следующим шагом является создание приложения в консоли Oracle Functions :

Разговорный интерфейс

Теперь мы можем развернуть приложение Fn для функций Oracle :

1
2
3
4
5
6
7
8
9
Eugenes-MacBook-Pro-3:fn fedor$ ls -l
total 8
-rw-r--r--@ 1 fedor  staff   12 Dec  4 15:41 app.yaml
drwxr-xr-x  5 fedor  staff  160 Feb  9 15:24 createsnapshotfn
drwxr-xr-x  6 fedor  staff  192 Feb  9 15:25 receiveFromBotFn
drwxr-xr-x  6 fedor  staff  192 Feb  9 15:25 sendToBotFn
Eugenes-MacBook-Pro-3:fn fedor$
Eugenes-MacBook-Pro-3:fn fedor$
Eugenes-MacBook-Pro-3:fn fedor$ fn deploy --all

Сделав это, мы можем наблюдать за приложением в консоли Oracle Functions :

Разговорный интерфейс

Следующий шаг — обновить URL-адреса API в чат-боте и на моем ноутбуке, чтобы вызывать функции в облаке вместо предыдущей локальной реализации. URL-адреса могут быть получены с помощью следующей команды:

1
fn list triggers odaapp

До сих пор переход с моего ноутбука на Oracle Functions выглядел довольно просто и легко. Но здесь немного боли. Для вызова функций, размещенных в Oracle Functions, с запросами http, запросы должны быть подписаны, чтобы они могли проходить проверку подлинности. Реализация node.js для вызова подписанного вызова функции выглядит следующим образом:

01
02
03
04
05
06
07
08
09
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
var fs = require('fs');
var https = require('https');
var os = require('os');
var httpSignature = require('http-signature');
var jsSHA = require("jssha");
 
var tenancyId = "ocid1.tenancy.oc1..aaaaaaaayonz5yhpr4vxqpbdof5rn7x5pfrlgjwjycwxasf4dkexiq";
var authUserId = "ocid1.user.oc1..aaaaaaaava2e3wd3cu6lew2sktd6by5hnz3d7prpgjho4oambterba";
var keyFingerprint = "88:3e:71:bb:a5:ea:68:b7:56:fa:3e:5d:ea:45:60:10";
var privateKeyPath = "/Users/fedor/.oci/functions_open.pem";
var privateKey = fs.readFileSync(privateKeyPath, 'ascii');
var identityDomain = "identity.us-ashburn-1.oraclecloud.com";
 
 
function sign(request, options) {
    var apiKeyId = options.tenancyId + "/" + options.userId + "/" + options.keyFingerprint;
 
    var headersToSign = [
        "host",
        "date",
        "(request-target)"
    ];
 
    var methodsThatRequireExtraHeaders = ["POST", "PUT"];
 
    if(methodsThatRequireExtraHeaders.indexOf(request.method.toUpperCase()) !== -1) {
        options.body = options.body || "";
        var shaObj = new jsSHA("SHA-256", "TEXT");
        shaObj.update(options.body);
 
        request.setHeader("Content-Length", options.body.length);
        request.setHeader("x-content-sha256", shaObj.getHash('B64'));
 
        headersToSign = headersToSign.concat([
            "content-type",
            "content-length",
            "x-content-sha256"
        ]);
    }
 
 
    httpSignature.sign(request, {
        key: options.privateKey,
        keyId: apiKeyId,
        headers: headersToSign
    });
 
    var newAuthHeaderValue = request.getHeader("Authorization").replace("Signature ", "Signature version=\"1\",");
    request.setHeader("Authorization", newAuthHeaderValue);
}
 
 
function handleRequest(callback) {
 
    return function(response) {
        var responseBody = "";
        response.on('data', function(chunk) {
        responseBody += chunk;
    });
 
 
        response.on('end', function() {
            callback(JSON.parse(responseBody));
        });
    }
}
 
 
function createSnapshot(release) {
 
    var body = release;
 
    var options = {
        host: 'af4qyj7yhva.us-phoenix-1.functions.oci.oraclecloud.com',
        path: '/t/createsnapshotfn',
        method: 'POST',
        headers: {
            "Content-Type": "application/text",
        }
    };
 
 
    var request = https.request(options, handleRequest(function(data) {
        console.log(data);
    }));
 
 
    sign(request, {
        body: body,
        privateKey: privateKey,
        keyFingerprint: keyFingerprint,
        tenancyId: tenancyId,
        userId: authUserId
    });
 
    request.end(body);
};

Этот подход должен использоваться пользовательскими компонентами Oracle Digital Assistant и компонентом слушателя на моем ноутбуке при вызове бессерверного API, размещенного в функциях Oracle .

Это оно!

Опубликовано на Java Code Geeks с разрешения Евгения Федоренко, партнера нашей программы JCG . См. Оригинальную статью здесь: пользовательский интерфейс разговора с Oracle Digital Assistant и Fn Project. Часть III Переезд в облако.

Мнения, высказанные участниками Java Code Geeks, являются их собственными.