Aviz Networks #
Workspace Defaults:
felixPrompt = `
Only use cards in your <answer> blocks. Only include cards that are relevant to the user's immediate message. Do not repeat the same cards more than once in your conversation.
When you use the query_semantic_db tool, after your prompt include the what the user asked you so the query_semantic_db agent has more context for the query.
If the user asks about device RMAs, ask the semantic DB tool to search for tickets regarding RMAs with the following prompt: "Find all tickets that mention RMA, including ticket IDs, links, and comments"
If the user is asking about devices actually being returned, you will have to look at the ticket comments for RMA numbers, shipping labels, etc. after you get the full list of tickets and comments from the semantic DB.
If the user is asking about problem areas, query the semantic DB for the tickets from last year. Then read the tickets and summarize the top problem areas yourself.
`
generatorPrompt = `
Some more examples:
Open tickets by customer
SELECT
substr(contact_email, instr(contact_email, '@') + 1) AS email_domain,
(select name from accounts where domain = substr(contact_email, instr(contact_email, '@') + 1) limit 1) AS account_name,
COUNT(*) AS open_ticket_count
FROM
tickets
WHERE
contact_email IS NOT NULL AND status NOT IN ('deleted', 'closed', 'solved')
AND instr(contact_email, '@') > 0
GROUP BY
email_domain
ORDER BY
open_ticket_count DESC;
Tickets this year by customer
SELECT
substr(contact_email, instr(contact_email, '@') + 1) AS email_domain,
(select name from accounts where domain = substr(contact_email, instr(contact_email, '@') + 1) limit 1) AS account_name,
COUNT(*) AS open_ticket_count
FROM
tickets
WHERE
contact_email IS NOT NULL AND status NOT IN ('deleted')
AND instr(contact_email, '@') > 0
AND timestamp >= '2025-01-01'
AND timestamp < '2026-01-01'
GROUP BY
email_domain
ORDER BY
open_ticket_count DESC;
Tickets received by Product this year
SELECT
custom_fields->>'Product' AS product,
COUNT(*) AS ticket_count
FROM
tickets
WHERE
timestamp >= '2025-01-01'
AND timestamp < '2026-01-01'
AND custom_fields->>'Product' IS NOT NULL
GROUP BY
custom_fields->>'Product'
ORDER BY
ticket_count DESC;
Current open issues by Product
SELECT
custom_fields->>'Product' AS product,
COUNT(*) AS open_ticket_count
FROM
tickets
WHERE
status NOT IN ('deleted', 'closed', 'solved')
AND custom_fields->>'Product' IS NOT NULL
GROUP BY
custom_fields->>'Product'
ORDER BY
open_ticket_count DESC;
Current open issues by Level
SELECT
custom_fields->>'Support Level' AS support_level,
COUNT(*) AS open_ticket_count
FROM
tickets
WHERE
status NOT IN ('deleted', 'closed', 'solved')
AND custom_fields->>'Support Level' IS NOT NULL
GROUP BY
custom_fields->>'Support Level'
ORDER BY
open_ticket_count DESC;
Tickets opened in 2025 by level
SELECT
custom_fields->>'Support Level' AS support_level,
COUNT(*) AS ticket_count
FROM
tickets
WHERE
timestamp >= '2025-01-01'
AND timestamp < '2026-01-01'
AND custom_fields->>'Support Level' IS NOT NULL
GROUP BY
custom_fields->>'Support Level'
ORDER BY
ticket_count DESC;
2025 Tickets by Vendor and by Levels
SELECT
custom_fields->>'Product/Switch Vendor' AS vendor,
SUM(CASE WHEN custom_fields->>'Support Level' = 'level1' THEN 1 ELSE 0 END) AS "Level 1",
SUM(CASE WHEN custom_fields->>'Support Level' = 'level2' THEN 1 ELSE 0 END) AS "Level 2",
SUM(CASE WHEN custom_fields->>'Support Level' = 'level3' THEN 1 ELSE 0 END) AS "Level 3",
SUM(CASE WHEN custom_fields->>'Support Level' = 'level3_internal' THEN 1 ELSE 0 END) AS "Level 3 (Internal)"
FROM
tickets
WHERE
timestamp >= '2025-01-01'
AND timestamp < '2026-01-01'
AND custom_fields->>'Product/Switch Vendor' IS NOT NULL
GROUP BY
custom_fields->>'Product/Switch Vendor'
ORDER BY
vendor;
2025 Tickets by Vendor
SELECT
custom_fields->>'Product/Switch Vendor' AS vendor,
COUNT(*) AS ticket_count
FROM
tickets
WHERE
timestamp >= '2025-01-01'
AND timestamp < '2026-01-01'
AND custom_fields->>'Product/Switch Vendor' IS NOT NULL
GROUP BY
custom_fields->>'Product/Switch Vendor'
ORDER BY
ticket_count DESC;
Issues received for EdgeCore2025 (By Customer)
SELECT
substr(contact_email, instr(contact_email, '@') + 1) AS email_domain,
COUNT(*) AS open_ticket_count
FROM
tickets
WHERE
contact_email IS NOT NULL
AND custom_fields->>'Product/Switch Vendor' = 'edgecore'
AND instr(contact_email, '@') > 0
AND timestamp >= '2025-01-01'
AND timestamp < '2026-01-01'
GROUP BY
email_domain
ORDER BY
open_ticket_count DESC;
Jan 2025 issues received for Celestica
SELECT
substr(contact_email, instr(contact_email, '@') + 1) AS email_domain,
COUNT(*) AS open_ticket_count
FROM
tickets
WHERE
contact_email IS NOT NULL
AND custom_fields->>'Product/Switch Vendor' = 'celestica'
AND instr(contact_email, '@') > 0
AND timestamp >= '2025-01-01'
AND timestamp < '2025-02-01'
GROUP BY
email_domain
ORDER BY
open_ticket_count DESC;
Jan 2025 issues received for Dell
SELECT
substr(contact_email, instr(contact_email, '@') + 1) AS email_domain,
COUNT(*) AS open_ticket_count
FROM
tickets
WHERE
contact_email IS NOT NULL
AND custom_fields->>'Product/Switch Vendor' = 'dell'
AND instr(contact_email, '@') > 0
AND timestamp >= '2025-01-01'
AND timestamp < '2025-02-01'
GROUP BY
email_domain
ORDER BY
open_ticket_count DESC;
Jan 2025 issues received for wistron
SELECT
substr(contact_email, instr(contact_email, '@') + 1) AS email_domain,
COUNT(*) AS open_ticket_count
FROM
tickets
WHERE
contact_email IS NOT NULL
AND custom_fields->>'Product/Switch Vendor' = 'wistron'
AND instr(contact_email, '@') > 0
AND timestamp >= '2025-01-01'
AND timestamp < '2025-02-01'
GROUP BY
email_domain
ORDER BY
open_ticket_count DESC;
Tickets regarding RMAs. This gives you the ticket ID, link, contact email, and all comments for tickets that mention RMA. Note that there is no LIMIT. The caller can handle the results.
select t.key->>'ticket_id' zendesk_ticket_id, t.key, t.link, t.contact_email, group_concat(tc.contact_email || '\n' || tc.text, '\n\n') all_comments from tickets t join ticket_comments tc on tc.ticket_id = t.id
WHERE
AND (MATCH_SYNONYMS('RMA', t.text) OR MATCH_SYNONYMS('RMA', t.title))
group by key
Top problem areas. This gives you the first ticket details.
select t.key->>'ticket_id' zendesk_ticket_id, t.key, t.link, t.contact_email, t.text, t.title, t.timestamp from tickets t
Weekly ticket counts for last 4 complete weeks for specific account
SELECT
'Week of ' ||
CASE CAST(strftime('%m', week_start) AS INTEGER)
WHEN 1 THEN 'January' WHEN 2 THEN 'February' WHEN 3 THEN 'March'
WHEN 4 THEN 'April' WHEN 5 THEN 'May' WHEN 6 THEN 'June'
WHEN 7 THEN 'July' WHEN 8 THEN 'August' WHEN 9 THEN 'September'
WHEN 10 THEN 'October' WHEN 11 THEN 'November' WHEN 12 THEN 'December'
END || ' ' ||
CAST(strftime('%d', week_start) AS INTEGER) ||
CASE
WHEN CAST(strftime('%d', week_start) AS INTEGER) % 10 = 1
AND CAST(strftime('%d', week_start) AS INTEGER) != 11 THEN 'st'
WHEN CAST(strftime('%d', week_start) AS INTEGER) % 10 = 2
AND CAST(strftime('%d', week_start) AS INTEGER) != 12 THEN 'nd'
WHEN CAST(strftime('%d', week_start) AS INTEGER) % 10 = 3
AND CAST(strftime('%d', week_start) AS INTEGER) != 13 THEN 'rd'
ELSE 'th'
END as Week,
COALESCE(SUM(CASE WHEN LOWER(wt.priority) = 'low' THEN 1 ELSE 0 END), 0) as Low,
COALESCE(SUM(CASE WHEN LOWER(wt.priority) = 'normal' THEN 1 ELSE 0 END), 0) as Normal,
COALESCE(SUM(CASE WHEN LOWER(wt.priority) = 'high' THEN 1 ELSE 0 END), 0) as High,
COALESCE(SUM(CASE WHEN LOWER(wt.priority) = 'urgent' THEN 1 ELSE 0 END), 0) as Urgent
FROM (
SELECT
n + 1 as week_order,
DATE('now', '-' || CAST(strftime('%w', DATE('now')) AS TEXT) || ' days', '-' || (n * 7 + 6) || ' days') as week_start,
DATE('now', '-' || CAST(strftime('%w', DATE('now')) AS TEXT) || ' days', '-' || (n * 7) || ' days') as week_end
FROM (SELECT 0 as n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3)
) weeks
LEFT JOIN (
-- Pre-filtered walmart tickets
SELECT t.id, t.timestamp, t.priority
FROM tickets t
JOIN ticket_contacts tc ON t.id = tc.ticket_id
JOIN contacts c ON tc.contact_id = c.id
WHERE c.domain = 'walmart.com'
) wt ON DATE(wt.timestamp) >= weeks.week_start AND DATE(wt.timestamp) <= weeks.week_end
GROUP BY weeks.week_order, weeks.week_start
ORDER BY weeks.week_order;
Monthly ticket counts for last 3 complete months for specific account
SELECT
CASE CAST(strftime('%m', month_start) AS INTEGER)
WHEN 1 THEN 'January' WHEN 2 THEN 'February' WHEN 3 THEN 'March'
WHEN 4 THEN 'April' WHEN 5 THEN 'May' WHEN 6 THEN 'June'
WHEN 7 THEN 'July' WHEN 8 THEN 'August' WHEN 9 THEN 'September'
WHEN 10 THEN 'October' WHEN 11 THEN 'November' WHEN 12 THEN 'December'
END || ' ' || strftime('%Y', month_start) as Month,
COALESCE(SUM(CASE WHEN LOWER(wt.priority) = 'low' THEN 1 ELSE 0 END), 0) as Low,
COALESCE(SUM(CASE WHEN LOWER(wt.priority) = 'normal' THEN 1 ELSE 0 END), 0) as Normal,
COALESCE(SUM(CASE WHEN LOWER(wt.priority) = 'high' THEN 1 ELSE 0 END), 0) as High,
COALESCE(SUM(CASE WHEN LOWER(wt.priority) = 'urgent' THEN 1 ELSE 0 END), 0) as Urgent
FROM (
-- Generate last 3 complete months
SELECT
n + 1 as month_order,
DATE('now', 'start of month', '-' || (n + 1) || ' months') as month_start,
DATE('now', 'start of month', '-' || n || ' months', '-1 day') as month_end
FROM (SELECT 0 as n UNION SELECT 1 UNION SELECT 2)
) months
LEFT JOIN (
-- Pre-filtered account tickets
SELECT t.id, t.timestamp, t.priority
FROM tickets t
JOIN ticket_contacts tc ON t.id = tc.ticket_id
JOIN contacts c ON tc.contact_id = c.id
JOIN accounts a ON c.domain = a.domain
WHERE a.account_id = '18455583541'
) wt ON DATE(wt.timestamp) >= months.month_start AND DATE(wt.timestamp) <= months.month_end
GROUP BY months.month_order, months.month_start
ORDER BY months.month_order;
Quarterly ticket counts for last 3 complete quarters for specific account domain
WITH quarter_ranges AS (
-- Generate 3 complete previous quarters
SELECT
n + 1 as quarter_order,
CASE
-- Calculate which quarter we're generating (going backwards from current)
WHEN ((CAST(strftime('%m', DATE('now')) AS INTEGER) - 1) / 3 + 1 - (n + 1)) <= 0
THEN ((CAST(strftime('%m', DATE('now')) AS INTEGER) - 1) / 3 + 1 - (n + 1)) + 4 -- Previous year
ELSE ((CAST(strftime('%m', DATE('now')) AS INTEGER) - 1) / 3 + 1 - (n + 1)) -- Current year
END as target_quarter,
CASE
WHEN ((CAST(strftime('%m', DATE('now')) AS INTEGER) - 1) / 3 + 1 - (n + 1)) <= 0
THEN CAST(strftime('%Y', DATE('now')) AS INTEGER) - 1 -- Previous year
ELSE CAST(strftime('%Y', DATE('now')) AS INTEGER) -- Current year
END as target_year
FROM (SELECT 0 as n UNION SELECT 1 UNION SELECT 2)
),
quarter_dates AS (
-- Convert quarter numbers to actual date ranges
SELECT
quarter_order,
'Q' || target_quarter || ' ' || target_year as quarter_label,
DATE(target_year || '-' || CASE target_quarter
WHEN 1 THEN '01-01' WHEN 2 THEN '04-01'
WHEN 3 THEN '07-01' WHEN 4 THEN '10-01'
END) as quarter_start,
DATE(target_year || '-' || CASE target_quarter
WHEN 1 THEN '03-31' WHEN 2 THEN '06-30'
WHEN 3 THEN '09-30' WHEN 4 THEN '12-31'
END) as quarter_end
FROM quarter_ranges
),
filtered_tickets AS (
-- Pre-filter tickets by domain
SELECT t.id, t.timestamp, t.priority
FROM tickets t
JOIN ticket_contacts tc ON t.id = tc.ticket_id
JOIN contacts c ON tc.contact_id = c.id
WHERE c.domain = 'walmart.com'
)
SELECT
qd.quarter_label as Quarter,
COALESCE(SUM(CASE WHEN LOWER(ft.priority) = 'low' THEN 1 ELSE 0 END), 0) as Low,
COALESCE(SUM(CASE WHEN LOWER(ft.priority) = 'normal' THEN 1 ELSE 0 END), 0) as Normal,
COALESCE(SUM(CASE WHEN LOWER(ft.priority) = 'high' THEN 1 ELSE 0 END), 0) as High,
COALESCE(SUM(CASE WHEN LOWER(ft.priority) = 'urgent' THEN 1 ELSE 0 END), 0) as Urgent
FROM quarter_dates qd
LEFT JOIN filtered_tickets ft ON DATE(ft.timestamp) >= qd.quarter_start
AND DATE(ft.timestamp) <= qd.quarter_end
GROUP BY qd.quarter_order, qd.quarter_label
ORDER BY qd.quarter_order;
---
**Guidelines for generating queries related to previous complete quarters** -
* Always show exactly 3 complete quarters (never current incomplete quarter)
* Generate quarter ranges first, then LEFT JOIN with filtered tickets (ensures zero-count quarters appear)
* Use proper quarter boundaries: Q1=Jan-Mar, Q2=Apr-Jun, Q3=Jul-Sep, Q4=Oct-Dec
* Don't use arbitrary date math like 'start of month', '-1 day'
* Don't include current quarter
Ticket details with SLA metrics (filtered for title and last 30 days but can be altered as required)
SELECT
link AS ticket_link,
REPLACE(title, '|', ' ') AS ticket_title,
priority AS severity,
timestamp AS ticket_receive_timestamp,
json_extract(data, '$.zendesk.metrics.initially_assigned_at') AS first_response_timestamp,
CASE
WHEN COALESCE(json_extract(data, '$.zendesk.metrics.reply_time_in_minutes.calendar'), 0) > 15 THEN 'Missed'
ELSE 'Ontime'
END AS SLA
FROM tickets
WHERE
title LIKE '%KDDI%'
AND timestamp >= datetime('now', '-30 days')
ORDER BY timestamp DESC;
`
labelAnalysisSystemPrompt = `You are a conversation analyzer for Aviz Networks. Aviz is a startup building networking solutions. You analyze text and transcripts for a Aviz's sales and/or customer success team. You analyze text to determine labels and associated sentiment.
The possible labels are:
- "pricing" - about pricing or costs
- "competitor" - about competitors or alternative products
- "personnel_change" - about a specific individual leaving their role in the customer's company, not regarding discontinuing use of a product.
- "feature_request" - request or interest in a new feature IN THE PRODUCT for Aviz Networks. Avoid feature requests regarding ProShort or meeting recorders.
- "task_issue_bug" - a task, issue, or bug REGARDING THE PRODUCT for Aviz Networks.
- "action_item" - a specific action item to follow up on, DOESN'T INCLUDE TRIVIAL ACKNOWLEDGEMENTS
Only label something if it's clearly one of those possible categories. A general question doesn't imply a feature request, task, issue, bug, or action item.
Sentiment is on a scale from -1 to 1. For example, -1 is really bad, -0.2 is negative but not that severe, and 1 meaning extremely thrilled. If the sentiment is unclear or insignificant, default to 0.
Example of sentiments:
- ok cool. i'll make it happen tomorrow morning. dont want things to go wrong at the end of the day
will let you know when it's done -> 0
- This is a critical bug and has material impact on our business -> -1
- Got it, thanks for the quick info! -> 0.2
First think through it and write down your thought using <thought></thought> tags.
and then respond with a JSON object with a "topics" property, which is an array of topics. A "topic" is a topic that is discussed with a specific label category. There may be multiple mentions of a topic, so they have to be summarized together. The same label mentioned in different contexts should be considered different topics.
Example:
<thought>The message is about pricing. It doesn't include any other topics. </thought>
{
"topics": [
{
"type": "pricing",
"sentiment": -1,
"summary": "Concern over pricing",
"excerpts": ["I think the quote is too much for us this year."]
},
{
"type": "pricing",
"sentiment": 1,
"summary": "Concern over pricing",
"excerpts": ["We like the ability to pay month to month."]
}
]
}
Conservative Tagging Example
If a message refers to a topic (such as 'personnel_change') but there is no business impact, risk, or opportunity—such as stating there are no changes or issues—do NOT output a topic for it. Only label genuinely meaningful signals.
<thought>This message states that there are no personnel changes. While it technically references a topic ("personnel_change"), it provides no actionable signal—there is no risk, no opportunity, and no change in the relationship. According to the guiding principle "be conservative," we should only include topics with clear business impact. Since this is a neutral update with zero impact and sentiment, it should be omitted entirely. The correct output is an empty list of topics.</thought>
{
"topics": []
}
`
conversationDiagnosisSystemPrompt = "You are an analysis agent for Aviz Networks. Aviz is a startup building networking solutions. Aviz uses Proshort to analyze meetings, Slack and Zendesk for chat and ticketing. You are analyzing notes and conversations for specific needle movers. The user is the head of customer success. They are interested in the needle movers from conversations. They are focused on details, so do not summarize anything. Provide as much detail as you can when you respond, including conversation/note titles, timestamps, and links (only if explicitly available). Organize your response by conversation/note, not by topic. They prioritize notes, so respond with information from notes first, then conversations. Use Markdown code syntax to escape things like `show <section>`. Avoid using markdown tables; prefer lists instead."
fetch('/api/workspace/defaults', {
method: 'put',
body: JSON.stringify({
conversations_prediction_weight: 0.08,
prompts: {
felix_system: felixPrompt,
query_generator_additional_instructions: generatorPrompt,
conversation_diagnosis_system: conversationDiagnosisSystemPrompt,
label_analysis_system: labelAnalysisSystemPrompt
}
})
});
Prediction models:
/* API CONFIGURATION */
let workspaceID = "0192f9b2-8211-7f04-b3ab-c526b8c093f1"; // Replace with your workspace ID
let BASE_API_URL = "/api";
/* Find feature names from https://app.funnelstory.ai/api/internal/prediction/models */
/* EXTRA CONFIGURATION FOR MODEL TRAINING FIELDS */
/*
additional_traits:
An array of strings representing additional traits.
Example: ["AI_advisor", "AI_answering", "pro", "starter"]
*/
let ADDITIONAL_TRAITS = [];
/*
known_positive_factors:
An array of strings representing factors known to contribute positively.
Example: ["activity:6_mo_cutoff:Had Online Orders", "activity:6_mo_cutoff:Hit 1K Followers"]
*/
let KNOWN_POSITIVE_FACTORS = [];
/*
known_negative_factors:
An array of strings representing factors known to have negative effects.
Example: ["activity:6_mo_cutoff:Negative Reviews", "trait:open_churn_case=true"]
*/
let KNOWN_NEGATIVE_FACTORS = [];
/*
exclude_factors:
An array of strings representing factors to exclude from training.
Example: ["property:last_month_impressions", "activity:6_mo_cutoff:Created User"]
*/
let EXCLUDE_FACTORS = [];
/*
Create safe fallbacks so that if any of the above are missing or not arrays,
they default to an empty array.
*/
let safeAdditionalTraits = Array.isArray(ADDITIONAL_TRAITS)
? ADDITIONAL_TRAITS
: [];
let safeKnownPositiveFactors = Array.isArray(KNOWN_POSITIVE_FACTORS)
? KNOWN_POSITIVE_FACTORS
: [];
let safeKnownNegativeFactors = Array.isArray(KNOWN_NEGATIVE_FACTORS)
? KNOWN_NEGATIVE_FACTORS
: [];
let safeExcludeFactors = Array.isArray(EXCLUDE_FACTORS)
? EXCLUDE_FACTORS
: [];
/* MAIN SCRIPT */
let trainWithAudiences = async (type) => {
// Fetch audiences (including hidden ones)
let response = await fetch(`${BASE_API_URL}/audiences?include_hidden=true`, {
method: "GET",
headers: {
"Content-Type": "application/json",
"fs-workspace-id": workspaceID,
},
});
let audiencesData = await response.json();
// Helper: Combine considered IDs from Churn and Retention audiences
let getCombinedConsideredIds = (audiences, type) => {
let churnAudience = audiences.find((aud) => aud.name === "Churn");
let retentionAudience = audiences.find((aud) => aud.name === "Retention");
if (type === "user") {
let churnUserIds = churnAudience ? churnAudience.data.matching_fs_user_ids : [];
let retentionUserIds = retentionAudience ? retentionAudience.data.matching_fs_user_ids : [];
return Array.from(new Set([...churnUserIds, ...retentionUserIds]));
} else {
let churnAccountIds = churnAudience ? churnAudience.data.matching_account_ids : [];
let retentionAccountIds = retentionAudience ? retentionAudience.data.matching_account_ids : [];
return Array.from(new Set([...churnAccountIds, ...retentionAccountIds]));
}
};
// For a given audience/model, build the training request body and execute the POST call
let trainModel = async (aud, model, consideredIds) => {
let url =
type === "user"
? `${BASE_API_URL}/internal/prediction/models/user_${model}/train`
: `${BASE_API_URL}/internal/prediction/models/${model}/train`;
let targetIds =
type === "user"
? { target_user_fsids: aud.data.matching_fs_user_ids }
: { target_account_ids: aud.data.matching_account_ids };
let consideredKey = type === "user" ? "considered_user_fsids" : "considered_account_ids";
// Training parameters
let params = {
num_trees: 25,
tree_depth: 500,
learning_rate: 0.1,
iterations: 1000,
lambda: 0.01,
regularizer: "ridge",
ensemble_weights: {"lr": 0.5, "rf": 0.5},
};
// Build the POST body including the extra configuration fields
let body = {
...targetIds,
[consideredKey]: consideredIds,
params,
additional_traits: safeAdditionalTraits,
known_positive_factors: safeKnownPositiveFactors,
known_negative_factors: safeKnownNegativeFactors,
exclude_factors: safeExcludeFactors,
// Only ignore target IDs when training the churn model
// ignore_target_ids: model === "churn", // YOU PROBABLY DON'T WANT THIS.
};
await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"fs-workspace-id": workspaceID,
},
body: JSON.stringify(body),
});
};
// Get audiences array (adjust based on your API response shape)
let audiencesArray = audiencesData.response.audiences;
let consideredIds = getCombinedConsideredIds(audiencesArray, type);
// Filter to include only hidden 'Churn' and 'Retention' audiences
let trainingAudiences = audiencesArray.filter(
(aud) => aud.hidden && (aud.name === "Churn" || aud.name === "Retention")
);
// Start training concurrently for each selected audience
let trainPromises = trainingAudiences.map((aud) => {
let model = aud.name.toLowerCase(); // Either "churn" or "retention"
return trainModel(aud, model, consideredIds);
});
await Promise.all(trainPromises);
// Update the scores after training
let updateUrl =
type === "user"
? `${BASE_API_URL}/internal/prediction/scores/users/update`
: `${BASE_API_URL}/internal/prediction/scores/accounts/update`;
await fetch(updateUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
"fs-workspace-id": workspaceID,
},
});
};
Email reports: #
Vendor tickets report #
I am creating a report of tickets. Use semantic DB. Give me each table as a CSV in a Markdown code block. Send as an email.
2025 tickets by vendor. Columns: vendor name, count.
2025 tickets by vendor and by levels. Columns: vendor name, level 1, level 2, level 3, level 3 (internal).
2025 tickets received for EdgeCore by customer. Columns: COALESCE(customer name, customer domain) as customer, count.
Jan 2025 issues received for Celestica. Columns: COALESCE(customer name, customer domain) as customer, count.
Jan 2025 issues received for Dell. Columns: COALESCE(customer name, customer domain) as customer, count.
Jan 2025 issues received for Wistron. Columns: COALESCE(customer name, customer domain) as customer, count.
Product tickets report #
I am creating a report of tickets. Use semantic DB. Give me each table as a CSV in a Markdown code block. Send as an email.
Tickets received by product this year. Columns: product name, count.
Current open tickets by product. Columns: product name, count.
Customer tickets report #
I am creating a report of tickets. Use semantic DB. Give me each table as a CSV in a Markdown code block. Send as an email.
Tickets received by customer this year. Columns: COALESCE(customer name, customer domain) as customer, count.
Current open tickets by customer. Columns: COALESCE(customer name, customer domain) as customer, count.
Current open tickets by level. Columns: level, count.
Tickets opened in 2025 by level. Columns: level, count.