@miso.ai/doggoganger 0.9.1-beta.17 → 0.9.1-beta.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/api/ask.js DELETED
@@ -1,134 +0,0 @@
1
- import { answer, questions } from '../data/index.js';
2
-
3
- const CPS = 100;
4
- const ITEMS_LOADING_TIME = 3;
5
- const STAGES = [
6
- {
7
- name: 'fetch',
8
- duration: 1.5,
9
- text: `Checking the question and fetching results... `,
10
- },
11
- {
12
- name: 'verify',
13
- duration: 1.5,
14
- text: `Verifying results... `,
15
- },
16
- {
17
- name: 'generate',
18
- duration: 1.5,
19
- text: `Generating answer... `,
20
- },
21
- ];
22
-
23
- export default class Ask {
24
-
25
- constructor(options = {}) {
26
- this._options = options;
27
- this._answers = new Map();
28
- }
29
-
30
- questions(payload, options = {}) {
31
- const answer = new Answer(payload, { ...this._options, ...options });
32
- const { question_id } = answer;
33
- this._answers.set(question_id, answer);
34
- return { question_id };
35
- }
36
-
37
- answer(questionId) {
38
- const answer = this._answers.get(questionId);
39
- if (!answer) {
40
- const error = new Error(`Question not found: ${questionId}`);
41
- error.status = 404;
42
- throw error;
43
- }
44
- return answer.get();
45
- }
46
-
47
- related_questions(payload) {
48
- return {
49
- related_questions: [...questions(payload)],
50
- };
51
- }
52
-
53
- }
54
-
55
- class Answer {
56
-
57
- constructor(payload, { answerFormat, answerSampling, answerLanguages, ...options } = {}) {
58
- this._options = Object.freeze(options);
59
- const timestamp = this.timestamp = Date.now();
60
- this._data = answer({ ...payload, timestamp }, { answerFormat, answerSampling, answerLanguages });
61
- }
62
-
63
- get question_id() {
64
- return this._data.question_id;
65
- }
66
-
67
- get() {
68
- const now = Date.now();
69
- const elapsed = (now - this.timestamp) * (this._options.speedRate || 1) / 1000;
70
- const [answer_stage, answer, finished] = this._answer(elapsed);
71
- const sources = this._sources(elapsed, finished);
72
- const related_resources = this._related_resources(elapsed, finished);
73
- const followup_questions = this._followup_questions(elapsed, finished);
74
- const { question_id, question, datetime, parent_question_id } = this._data;
75
-
76
- return {
77
- answer,
78
- answer_stage,
79
- datetime,
80
- finished,
81
- parent_question_id,
82
- question,
83
- question_id,
84
- sources,
85
- related_resources,
86
- followup_questions,
87
- };
88
- }
89
-
90
- _answer(elapsed) {
91
- for (const stage of STAGES) {
92
- elapsed -= stage.duration;
93
- if (elapsed < 0) {
94
- return [stage.name, stage.text, false];
95
- }
96
- }
97
- const { answer } = this._data;
98
- const length = Math.floor(elapsed * CPS);
99
- const finished = length >= answer.length;
100
- const text = finished ? answer : answer.slice(0, length);
101
- return ['result', text, finished];
102
- }
103
-
104
- _sources(elapsed, finished) {
105
- const { sources } = this._data;
106
- if (finished) {
107
- return sources;
108
- }
109
- const { length } = sources;
110
- const loaded = Math.floor(length * elapsed / ITEMS_LOADING_TIME);
111
- return sources.slice(0, loaded);
112
- }
113
-
114
- _related_resources(elapsed, finished) {
115
- const { related_resources } = this._data;
116
- if (finished) {
117
- return related_resources;
118
- }
119
- const { length } = related_resources;
120
- const loaded = Math.floor(length * elapsed / ITEMS_LOADING_TIME);
121
- return related_resources.slice(0, loaded);
122
- }
123
-
124
- _followup_questions(elapsed, finished) {
125
- const { followup_questions } = this._data;
126
- if (finished || !followup_questions) {
127
- return followup_questions;
128
- }
129
- const { length } = followup_questions;
130
- const loaded = Math.floor(length * elapsed / ITEMS_LOADING_TIME);
131
- return followup_questions.slice(0, loaded);
132
- }
133
-
134
- }
package/src/api/index.js DELETED
@@ -1,17 +0,0 @@
1
- import Ask from './ask.js';
2
- import Search from './search.js';
3
- import Recommendation from './recommendation.js';
4
- import Interactions from './interactions.js';
5
- import Products from './products.js';
6
-
7
- export default class Api {
8
-
9
- constructor(options) {
10
- this.ask = new Ask(options);
11
- this.search = new Search(options);
12
- this.recommendation = new Recommendation(options);
13
- this.interactions = new Interactions(options);
14
- this.products = new Products(options);
15
- }
16
-
17
- }
@@ -1,13 +0,0 @@
1
- export default class Interactions {
2
-
3
- constructor(options) {
4
- this._options = options;
5
- }
6
-
7
- upload(records) {
8
- return [];
9
- }
10
-
11
- // TODO: delete
12
-
13
- }
@@ -1,28 +0,0 @@
1
- export default class Products {
2
-
3
- constructor(options) {
4
- this._options = options;
5
- }
6
-
7
- upload(records) {
8
- return [];
9
- }
10
-
11
- ids() {
12
- const ids = [];
13
- for (let i = 0; i < 5000; i++) {
14
- ids.push(mockProductId(i));
15
- }
16
- return {
17
- ids,
18
- };
19
- }
20
-
21
- // TODO: delete (batch)
22
-
23
- }
24
-
25
- function mockProductId(i) {
26
- const prefix = i < 10 ? 'p_000' : i < 100 ? 'p_00' : i < 1000 ? 'p_0' : 'p_';
27
- return `${prefix}${i}`;
28
- }
@@ -1,21 +0,0 @@
1
- import { products } from '../data/index.js';
2
-
3
- export default class Recommendation {
4
-
5
- constructor(options) {
6
- this._options = options;
7
- }
8
-
9
- user_to_products({ rows = 5 }) {
10
- return {
11
- products: [...products({ rows })],
12
- };
13
- }
14
-
15
- product_to_products({ rows = 5 }) {
16
- return {
17
- products: [...products({ rows })],
18
- };
19
- }
20
-
21
- }
package/src/api/search.js DELETED
@@ -1,15 +0,0 @@
1
- import { products } from '../data/index.js';
2
-
3
- export default class Search {
4
-
5
- constructor(options) {
6
- this._options = options;
7
- }
8
-
9
- search({ rows = 5 }) {
10
- return {
11
- products: [...products({ rows })],
12
- };
13
- }
14
-
15
- }
@@ -1,53 +0,0 @@
1
- import { randomInt, formatDatetime, sample, uuid, shuffle } from './utils.js';
2
- import * as fields from './fields.js';
3
- import { articles } from './articles.js';
4
- import { questions } from './questions.js';
5
-
6
- export function answer({
7
- question,
8
- parent_question_id,
9
- source_fl = ['cover_image', 'url'],
10
- related_resource_fl = ['cover_image', 'url'],
11
- cite_link = false,
12
- cite_start = '[',
13
- cite_end = ']',
14
- timestamp = Date.now(),
15
- }, { answerFormat = 'markdown', answerSampling, answerLanguages = [] } = {}) {
16
-
17
- const question_id = uuid();
18
- const datetime = formatDatetime(timestamp);
19
-
20
- const sampling = answerSampling !== undefined ? Math.max(0, Math.min(1, answerSampling)) : undefined;
21
- const features = answerLanguages.length ? answerLanguages.map(language => `lang-${language}`) : undefined;
22
-
23
- const related_resources = [...articles({ rows: sampleRandomInt(6, 8, sampling), fl: related_resource_fl })].map(excludeHtml);
24
- const sources = [...articles({ rows: sampleRandomInt(4, 6, sampling), fl: source_fl })].map(excludeHtml);
25
-
26
- const citation = {
27
- link: cite_link !== '0' && !!cite_link,
28
- start: cite_start,
29
- end: cite_end,
30
- unused: shuffle([...Array(sources.length).keys()]),
31
- };
32
- const answer = fields.answer({ sources, citation, format: answerFormat, sampling, features });
33
- const followup_questions = [...questions({ rows: sampleRandomInt(3, 6) })];
34
-
35
- return {
36
- question,
37
- question_id,
38
- ...(parent_question_id && { parent_question_id }),
39
- datetime,
40
- answer,
41
- sources,
42
- related_resources,
43
- followup_questions,
44
- };
45
- }
46
-
47
- function sampleRandomInt(min, max, sampling) {
48
- return randomInt(sample(min, sampling), sample(max, sampling));
49
- }
50
-
51
- function excludeHtml({ html, ...rest }) {
52
- return rest;
53
- }
@@ -1,51 +0,0 @@
1
- import * as u from './utils.js';
2
- import * as fields from './fields.js';
3
-
4
- const FIELDS = new Set([
5
- 'cover_image',
6
- 'url',
7
- 'created_at',
8
- 'updated_at',
9
- 'published_at',
10
- ]);
11
-
12
- export function *articles({ rows, ...options } = {}) {
13
- for (let i = 0; i < rows; i++) {
14
- yield article({ ...options, index: i });
15
- }
16
- }
17
-
18
- function article({ html, fl = [] } = {}) {
19
- const id = u.id();
20
-
21
- const article = {
22
- product_id: id,
23
- authors: fields.authors(),
24
- categories: [],
25
- tags: fields.tags(),
26
- title: fields.title({ size: [4, 10] }),
27
- snippet: fields.description({ size: [20, 40] }),
28
- html: fields.html(html),
29
- };
30
-
31
- for (const field of fl) {
32
- if (FIELDS.has(field)) {
33
- article[field] = property(article, field);
34
- }
35
- }
36
-
37
- return article;
38
- }
39
-
40
- function property({ product_id }, field) {
41
- switch (field) {
42
- case 'cover_image':
43
- return fields.image();
44
- case 'url':
45
- return `/products/${product_id}`;
46
- case 'created_at':
47
- case 'updated_at':
48
- case 'published_at':
49
- return fields.date();
50
- }
51
- }
@@ -1,105 +0,0 @@
1
- import * as lorem from './lorem.js';
2
- import { imageUrl, sample } from './utils.js';
3
- import * as md from './markdown/index.js';
4
-
5
- const DAY = 1000 * 60 * 60 * 24;
6
- const WEEK = DAY * 7;
7
-
8
- export function date({} = {}) {
9
- const now = Date.now();
10
- const max = now - DAY;
11
- const min = max - WEEK * 8;
12
- return new Date(min + Math.random() * (max - min)).toISOString();
13
- }
14
-
15
- export function image({ size = 300 } = {}) {
16
- return imageUrl(size);
17
- }
18
-
19
- export function authors({ size = [1, 3] } = {}) {
20
- return lorem.lorem({
21
- size,
22
- decorates: ['title'],
23
- output: 'array',
24
- });
25
- }
26
-
27
- export function tags({ size = [1, 4] } = {}) {
28
- return lorem.lorem({
29
- size,
30
- output: 'array',
31
- });
32
- }
33
-
34
- // TODO: categories
35
-
36
- export function title({ size = [2, 6] } = {}) {
37
- return lorem.lorem({
38
- size,
39
- decorates: ['title'],
40
- });
41
- }
42
-
43
- export function description({ size = [10, 20], ...options } = {}) {
44
- const decorator = Object.keys(options).length ? ['description', options] : 'description';
45
- return lorem.lorem({
46
- size,
47
- decorates: [decorator],
48
- });
49
- }
50
-
51
- export function html({ paragraphs = 8, sections, paragraph, image: imageOptions } = {}) {
52
- paragraph = {
53
- size: [30, 60],
54
- ...paragraph,
55
- };
56
- imageOptions = {
57
- size: [480, 270],
58
- ...imageOptions,
59
- };
60
- if (sections === undefined) {
61
- sections = Math.floor(paragraphs * (1 + Math.random()) / 4);
62
- }
63
- sections = Math.max(1, Math.min(sections, paragraphs));
64
- const content = [];
65
- const pps = paragraphs / sections;
66
- let j = 0;
67
- for (let i = 0; i < sections; i++) {
68
- if (i > 0) {
69
- content.push(`<h4>${title()}</h4>`);
70
- }
71
- while (j++ < (i + 1) * pps) {
72
- content.push(`<p>${description(paragraph)}</p>`);
73
- }
74
- content.push(`<div class="image-container"><img src="${image(imageOptions)}"></div>`);
75
- }
76
- return content.join('');
77
- }
78
-
79
- export function availability() {
80
- return Math.random() > 0.3 ? 'IN_STOCK' : 'OUT_OF_STOCK';
81
- }
82
-
83
- export function price() {
84
- return Math.floor(Math.random() * 10000) / 100;
85
- }
86
-
87
- export function rating() {
88
- return Math.floor(Math.random() * 500) / 100 + 1;
89
- }
90
-
91
- export function answer({ sources, format, citation, sampling, features }) {
92
- switch (format) {
93
- case 'markdown':
94
- let index = 1;
95
- sources = sources.map(({ url }) => ({ url, index: index++ }));
96
- return md.markdown({ sources, citation, sampling, features });
97
- case 'plaintext':
98
- default:
99
- return lorem.lorem({
100
- min: sample(50, sampling),
101
- max: sample(50, sampling),
102
- decorates: ['description'],
103
- });
104
- }
105
- }
package/src/data/index.js DELETED
@@ -1,10 +0,0 @@
1
- import * as md from './markdown/index.js';
2
- import * as lorem from './lorem.js';
3
- import * as utils from './utils.js';
4
- import * as fields from './fields.js';
5
-
6
- export { md, lorem, utils, fields };
7
- export * from './products.js';
8
- export * from './articles.js';
9
- export * from './questions.js';
10
- export * from './answers.js';
package/src/data/lorem.js DELETED
@@ -1,145 +0,0 @@
1
- import { randomInt, gaussRandom, iterateWithLastItemSignal as iterateWithLastItemSignal } from './utils.js';
2
- import DEFAULT_WORDS from './words.js';
3
-
4
- export function lorem({ decorates = [], output = 'string', size, min, max, ...options } = {}) {
5
- let iterator = limit(size || [min, max])(base(options));
6
- for (const decorate of decorates) {
7
- iterator = lookup(decorate)(iterator);
8
- }
9
- return lookup(output)(iterator);
10
- }
11
-
12
- const FNS = {
13
- string,
14
- array,
15
- title,
16
- description,
17
- multiline,
18
- }
19
-
20
- function lookup(fn) {
21
- switch (typeof fn) {
22
- case 'string':
23
- return FNS[fn]();
24
- case 'function':
25
- return fn;
26
- case 'object':
27
- if (Array.isArray(fn)) {
28
- const [name, options = {}] = fn;
29
- return FNS[name](options);
30
- }
31
- }
32
- throw new Error(`Unrecognized decorator/output form: ${fn}`);
33
- }
34
-
35
- // base //
36
- export function *base({ words = DEFAULT_WORDS, fixedStarts = 0 } = {}) {
37
- const wordsLength = words.length;
38
- for (let i = 0; ; i++) {
39
- yield words[i < fixedStarts ? i : Math.floor(Math.random() * wordsLength)];
40
- }
41
- }
42
-
43
- // output //
44
- export function string({ separator = ' ' } = {}) {
45
- return iterator => [...iterator].join(separator);
46
- }
47
-
48
- export function array() {
49
- return iterator => [...iterator];
50
- }
51
-
52
- export function multiline({
53
- wordsPerLine = {
54
- avg: 10,
55
- std: 3,
56
- min: 1,
57
- },
58
- } = {}) {
59
- return iterator => {
60
- let slen = gaussMS(wordsPerLine);
61
- let result = '';
62
- for (let word of iterator) {
63
- if (result) {
64
- if (slen-- === 0) {
65
- result += '\n';
66
- slen = gaussMS(wordsPerLine);
67
- } else {
68
- result += ' ';
69
- }
70
- }
71
- result += word;
72
- }
73
- return result;
74
- }
75
- }
76
-
77
- // decorators //
78
- export function limit(size = [5, 10]) {
79
- const n = typeof size === 'number' ? size : randomInt(...size);
80
- return function *(iterator) {
81
- let i = 0;
82
- for (let word of iterator) {
83
- if (i++ >= n) {
84
- break;
85
- }
86
- yield word;
87
- }
88
- };
89
- }
90
-
91
- export function title({} = {}) {
92
- return function *(iterator) {
93
- for (let word of iterator) {
94
- yield capitalize(word);
95
- }
96
- };
97
- }
98
-
99
- export function description({
100
- wordsPerSentence = {
101
- avg: 24,
102
- std: 5,
103
- min: 1,
104
- },
105
- punctuation = '.',
106
- } = {}) {
107
- return function *(iterator) {
108
- let slen = 0;
109
-
110
- yield* iterateWithLastItemSignal(iterator, function *(word, last) {
111
- if (slen === 0) {
112
- word = capitalize(word);
113
- slen = gaussMS(wordsPerSentence);
114
- }
115
- if (--slen === 0 || last) {
116
- word += punctuation;
117
- }
118
- yield word;
119
- });
120
- };
121
- }
122
-
123
- // helpers //
124
- function capitalize(word) {
125
- return word[0].toUpperCase() + word.substring(1);
126
- }
127
-
128
- // TODO: have a random variable expression
129
- function gaussMS(args) {
130
- if (typeof args === 'number') {
131
- return Math.round(avg);
132
- }
133
- let { avg, std, min, max } = args;
134
- if (std === undefined) {
135
- std = avg / 4;
136
- }
137
- let n = gaussRandom() * std + avg;
138
- if (min !== undefined) {
139
- n = Math.max(min, n);
140
- }
141
- if (max !== undefined) {
142
- n = Math.min(max, n);
143
- }
144
- return Math.round(n);
145
- }