Exploring Ctrip Flight IVR Visual Platform: Architecture, Evolution, and Implementation
This article details the evolution of Ctrip's flight IVR system from a simple Chinese‑only version to a multilingual, fully visualized low‑code platform, describing its architecture, core components such as data definition, rule and script engines, version management, and the underlying Node.js and React technologies.
IVR (Interactive Voice Response) allows callers to navigate services via voice prompts, reducing the load on human agents; the article introduces Ctrip's flight IVR visual system and its benefits.
The original IVR (V1.0) targeted domestic users, using a fixed InTag/OutTag strategy pattern that kept business logic flat and required only tag additions for new scenarios.
With global expansion, V2.0 added over 20 language lines, exposing problems such as exploding configuration switches, non‑visual process flows, and inefficient speech‑template management, prompting a redesign toward a visual, configurable platform.
A comparison table highlights key differences: V1.0 supports only Chinese, has no visual flow, hard‑coded tags, and manual speech configuration; V2.0 offers multilingual support, fully visualized processes and call traces, configuration‑driven business logic, and a visual speech‑template editor.
The new IVR visual platform consists of two parts: a management page for editing visual answer trees, version control, and call‑trace queries, and a self‑service engine that parses the configured trees to provide automated responses.
Core components include global data definition (providing a schema for all subsequent configurations), a rule engine (built on react‑awesome‑query‑builder) for conditional branching, a script engine (JavaScript scripts edited with Monaco Editor) for service calls and data transformation, and a dynamic speech‑template system supporting loops, formatting, and time placeholders.
Implementation details cover: defining data types (string, integer, boolean, etc.) before rule or script creation; constructing the flow tree using AntV G6 with node types distinguished by color and icons; extending the rule engine to output JavaScript; integrating Monaco for intelligent script editing; executing scripts safely inside a VM2 sandbox with limited modules and pre‑compiled VMScript for performance; and managing multiple versions (draft, pre‑release, gray, and production) to ensure stability while allowing rapid iteration.
// Extra type definitions for Monaco suggestions
MonacoEditorManager.setExtraLibs([{ content: extraLib }]);
MonacoEditorManager.addPageSuggestionCallback("TriggerListDialog", (model: any, position: any) => {
const text = model.getValueInRange({
startLineNumber: position.lineNumber,
startColumn: 1,
endLineNumber: position.lineNumber,
endColumn: position.column
});
// Custom suggestions
return getSuggestions(text, props.getPropertiesCallback, () => props.serviceOperations);
});
// Build __debug_script.js file
const loadScriptCode = (scriptString: string) => {
const sourceUrl = '//# sourceURL=__debug_script.js';
const functionDef = 'async function __debug_script(Props, getPropertyValue, setPropertyValue, invokeServiceMethod) {';
const scriptLines = (scriptString?.split('\n') || []).map(line => ' ' + line);
const lines = [sourceUrl, functionDef, ...scriptLines, '}'];
const codeNode = window.document.createTextNode(lines.join('\n'));
const script = window.document.createElement('script');
script.type = 'text/javascript';
script.appendChild(codeNode);
window.document.body.appendChild(script);
return scriptString;
};
// Execute script in debug console
const debugCode = async (inputPropertyValues) => {
// Pass parameters and run script
window["__debug_script"](Props, getPropertyValue, setPropertyValue, invokeServiceMethod);
// ...
};
// Script compilation
const vmScript = `const asyncFunction = async () => =>{\n${this.script}\n};\nasyncFunction().then(result=>onVmScriptComplete(result)).catch(error=>onVmScriptError(error));`;
this.vmScript = new VMScript(vmScript).compile();
// Run script in VM2 sandbox
const runInVM = (param: object, callback: () => void = null): any => {
return new Promise((resolve, reject) => {
const vm = new NodeVM({
console: 'inherit',
sandbox: {
...param,
onVmScriptComplete: (result) => resolve(result),
onVmScriptError: (error) => reject(error)
}
});
vm.run(this.vmScript);
});
};The platform has been stable for nearly a year, greatly improving cross‑team communication, and future work includes integrating AI/ASR technologies to further enhance voice interaction.
Ctrip Technology
Official Ctrip Technology account, sharing and discussing growth.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.