bonito/
lib.rs

1
2
3/// task types for bonito
4pub enum TaskType {
5    ExtractiveQuestionAnswering,
6    MultipleChoiceQuestionAnswering,
7    QuestionGeneration,
8    QuestionAnsweringWithoutChoices,
9    YesNoQuestionAnswering,
10    CoreferenceResolution,
11    ParaphraseGeneration,
12    ParaphraseIdentification,
13    SentenceCompletion,
14    Sentiment,
15    Summarization,
16    TextGeneration,
17    TopicClassification,
18    WordSenseDisambiguation,
19    TextualEntailment,
20    NaturalLanguageInference,
21}
22
23/// maps a short task string (e.g. "exqa") to a `TaskType`
24pub fn str_to_task_type(task_type_str: &str) -> Option<TaskType> {
25    match task_type_str {
26        "exqa" => Some(TaskType::ExtractiveQuestionAnswering),
27        "mcqa" => Some(TaskType::MultipleChoiceQuestionAnswering),
28        "qg" => Some(TaskType::QuestionGeneration),
29        "qa" => Some(TaskType::QuestionAnsweringWithoutChoices),
30        "ynqa" => Some(TaskType::YesNoQuestionAnswering),
31        "coref" => Some(TaskType::CoreferenceResolution),
32        "paraphrase" => Some(TaskType::ParaphraseGeneration),
33        "paraphrase_id" => Some(TaskType::ParaphraseIdentification),
34        "sent_comp" => Some(TaskType::SentenceCompletion),
35        "sentiment" => Some(TaskType::Sentiment),
36        "summarization" => Some(TaskType::Summarization),
37        "text_gen" => Some(TaskType::TextGeneration),
38        "topic_class" => Some(TaskType::TopicClassification),
39        "wsd" => Some(TaskType::WordSenseDisambiguation),
40        "te" => Some(TaskType::TextualEntailment),
41        "nli" => Some(TaskType::NaturalLanguageInference),
42        _ => None,
43    }
44}
45
46/// maps a `TaskType` to a (long) string (e.g. "multiple-choice question answering") which is used in prompt
47/// ref https://github.com/BatsResearch/bonito/blob/main/bonito/model.py#L106C13-L106C27
48pub fn task_type_to_task_prompt(task_type: &TaskType) -> Option<String> {
49    match task_type {
50        TaskType::ExtractiveQuestionAnswering => Some("extractive question answering".to_string()),
51        TaskType::MultipleChoiceQuestionAnswering => {
52            Some("multiple-choice question answering".to_string())
53        }
54        TaskType::QuestionGeneration => Some("question generation".to_string()),
55        TaskType::QuestionAnsweringWithoutChoices => {
56            Some("question answering without choices".to_string())
57        }
58        TaskType::YesNoQuestionAnswering => Some("yes-no question answering".to_string()),
59        TaskType::CoreferenceResolution => Some("coreference resolution".to_string()),
60        TaskType::ParaphraseGeneration => Some("paraphrase generation".to_string()),
61        TaskType::ParaphraseIdentification => Some("paraphrase identification".to_string()),
62        TaskType::SentenceCompletion => Some("sentence completion".to_string()),
63        TaskType::Sentiment => Some("sentiment".to_string()),
64        TaskType::Summarization => Some("summarization".to_string()),
65        TaskType::TextGeneration => Some("text generation".to_string()),
66        TaskType::TopicClassification => Some("topic classification".to_string()),
67        TaskType::WordSenseDisambiguation => Some("word sense disambiguation".to_string()),
68        TaskType::TextualEntailment => Some("textual entailment".to_string()),
69        TaskType::NaturalLanguageInference => Some("natural language inference".to_string()),
70    }
71}
72
73/// returns the prompt for the model based on the task type
74fn get_prompt_by_task_type(context: &str, task_prompt: &str) -> String {
75    let mut prompt = String::from("<|tasktype|>\n");
76    prompt.push_str(task_prompt);
77    prompt.push_str("\n<|context|>\n");
78    prompt.push_str(context);
79    prompt.push_str("\n<|task|>\n ");
80    prompt
81}
82
83/// parse the bonito LLM generated completion and return the question in string
84/// only works with prompt with "exqa"/"multiple-choice question answering"
85/// None if no question found
86pub fn parse_q(completion: &str, test_chunk: &str) -> Option<String> {
87    let pair: Vec<_> = completion.split("<|pipe|>").collect();
88    // no <|pipe|> found, return None
89    if pair.len() == 0 {
90        return None;
91    }
92
93    let before_pipe = pair[0];
94    if before_pipe.contains("Q:") {
95        // try first to find "Q: A:"
96        // split the string by "Q:"
97        let pair_q: Vec<_> = before_pipe.split("Q:").collect();
98        // and take the second part
99        let after_q = pair_q[1];
100
101        // remove and return if there is `Referring to the passage above, the correct answer to the given question is`
102        if after_q
103            .contains("Referring to the passage above, the correct answer to the given question is")
104        {
105            let pair_q: Vec<_> = after_q
106                .split(
107                    "Referring to the passage above, the correct answer to the given question is",
108                )
109                .collect();
110            let after_q = pair_q[0];
111            let trimmed = after_q.trim().to_string();
112            if trimmed.len() > 0 {
113                return Some(trimmed);
114            }
115        }
116
117        // remove and return if there is `A:`
118        if after_q.contains("A:") {
119            // try to split the string by "A:"
120            let pair_a: Vec<_> = after_q.split("A:").collect();
121            // and take the first part
122            let after_a = pair_a[0];
123
124            // remove if there is `{{context}}`
125            if after_a.contains("{{context}}") {
126                let pair_q: Vec<_> = after_q.split("{{context}}").collect();
127                let after_q = pair_q[0];
128                let trimmed = after_q.trim().to_string();
129                if trimmed.len() > 0 {
130                    return Some(trimmed);
131                }
132            }
133
134            let trimmed = after_a.trim().to_string();
135            if trimmed.len() > 0 {
136                return Some(trimmed);
137            }
138        }
139    }
140
141    if before_pipe.contains("Question:") {
142        // split the string by "Q:"
143        let pair_question: Vec<_> = before_pipe.split("Question:").collect();
144        let after_question = pair_question[1];
145        let trimmed = after_question.trim().to_string();
146        if trimmed.len() > 0 {
147            return Some(trimmed);
148        }
149    }
150
151    if before_pipe.contains("What is the answer for the question:") {
152        let pair_q: Vec<_> = before_pipe
153            .split("What is the answer for the question:")
154            .collect();
155
156        // and take the second part
157        let after_q = pair_q[1];
158        // remove if there is `{{context}}`
159        if after_q.contains("{{context}}") {
160            let pair_q: Vec<_> = after_q.split("{{context}}").collect();
161            let after_q = pair_q[0];
162            let trimmed = after_q.trim().to_string();
163            if trimmed.len() > 0 {
164                return Some(trimmed);
165            }
166        }
167
168        let trimmed = after_q.trim().to_string();
169        if trimmed.len() > 0 {
170            return Some(trimmed);
171        }
172    }
173
174    if before_pipe.contains("answer the following question:") {
175        let pair_q: Vec<_> = before_pipe
176            .split("answer the following question:")
177            .collect();
178
179        // and take the second part
180        let after_q = pair_q[1];
181        // remove if there is `{{context}}`
182        if after_q.contains("{{context}}") {
183            let pair_q: Vec<_> = after_q.split("{{context}}").collect();
184            let after_q = pair_q[0];
185            let trimmed = after_q.trim().to_string();
186            if trimmed.len() > 0 {
187                return Some(trimmed);
188            }
189        }
190
191        let trimmed = after_q.trim().to_string();
192        if trimmed.len() > 0 {
193            return Some(trimmed);
194        }
195    }
196
197    if before_pipe
198        .contains("Given the paragraph above, please answer correctly the following question:")
199    {
200        let pair_q: Vec<_> = before_pipe
201            .split("Given the paragraph above, please answer correctly the following question:")
202            .collect();
203
204        // and take the second part
205        let after_q = pair_q[1];
206        // remove if there is `Hint: {{context}}`
207        if after_q.contains("Hint: {{context}}") {
208            let pair_q: Vec<_> = after_q.split("Hint: {{context}}").collect();
209            let after_q = pair_q[0];
210            let trimmed = after_q.trim().to_string();
211            if trimmed.len() > 0 {
212                return Some(trimmed);
213            }
214        }
215
216        let trimmed = after_q.trim().to_string();
217        if trimmed.len() > 0 {
218            return Some(trimmed);
219        }
220    }
221
222    // no prefixes found, return whatever between "<|task|>" and "<|pipe|>"
223    let pair: Vec<_> = before_pipe.split("<|task|>").collect();
224    let after_task = pair[1];
225
226    // remove if there is `Hint: {{context}}`
227    if after_task.contains("Hint: {{context}}") {
228        let pair: Vec<_> = after_task.split("Hint: {{context}}").collect();
229        let after = pair[0];
230        let trimmed = after.trim().to_string();
231        if trimmed.len() > 0 {
232            return Some(trimmed);
233        }
234    }
235
236    // add the test_chunk if `Given the background: {{context}}`
237    if after_task.contains("Given the background: {{context}}") {
238        let pair: Vec<_> = after_task
239            .split("Given the background: {{context}}")
240            .collect();
241        let after_given_background = pair[1];
242        let with_context = format!(
243            "Given the background: {}\n{}",
244            test_chunk, after_given_background
245        );
246        let trimmed = with_context.trim().to_string();
247        if trimmed.len() > 0 {
248            return Some(trimmed);
249        }
250    }
251
252    // add the context if `use this background: {{context}}`
253    if after_task.contains("use this background: {{context}}") {
254        let after_task = after_task.replace("{{context}}", test_chunk);
255        let trimmed = after_task.trim().to_string();
256        if trimmed.len() > 0 {
257            return Some(trimmed);
258        }
259    }
260
261    let trimmed = after_task.trim().to_string();
262    if trimmed.len() > 0 {
263        return Some(trimmed);
264    }
265
266    // if can't find "Q:" or ""
267    None
268}
269
270/// parse the bonito LLM generated completion and return the answer in string
271/// only works with prompt with "exqa"/"multiple-choice question answering"
272/// None if no answer found
273pub fn parse_a(completion: &str) -> Option<String> {
274    let pair: Vec<_> = completion.split("<|pipe|>").collect();
275
276    if pair.len() > 0 {
277        return Some(pair[1].trim().to_string());
278    }
279
280    return None;
281}
282
283/// prepares the prompt for the model based on `TaskType`
284// ref https://github.com/BatsResearch/bonito/blob/main/bonito/model.py#L81
285pub fn prepare_prompt(context: &str, task_type: &TaskType) -> String {
286    match task_type {
287        TaskType::ExtractiveQuestionAnswering => {
288            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
289        }
290        TaskType::MultipleChoiceQuestionAnswering => {
291            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
292        }
293        TaskType::QuestionGeneration => {
294            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
295        }
296        TaskType::QuestionAnsweringWithoutChoices => {
297            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
298        }
299        TaskType::YesNoQuestionAnswering => {
300            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
301        }
302        TaskType::CoreferenceResolution => {
303            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
304        }
305        TaskType::ParaphraseGeneration => {
306            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
307        }
308        TaskType::ParaphraseIdentification => {
309            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
310        }
311        TaskType::SentenceCompletion => {
312            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
313        }
314        TaskType::Sentiment => {
315            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
316        }
317        TaskType::Summarization => {
318            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
319        }
320        TaskType::TextGeneration => {
321            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
322        }
323        TaskType::TopicClassification => {
324            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
325        }
326        TaskType::WordSenseDisambiguation => {
327            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
328        }
329        TaskType::TextualEntailment => {
330            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
331        }
332        TaskType::NaturalLanguageInference => {
333            get_prompt_by_task_type(&context, &task_type_to_task_prompt(task_type).unwrap())
334        }
335    }
336}
337
338#[cfg(test)]
339mod tests {
340    use super::*;
341
342    // covers the following cases:
343    // - `Question: `
344    // - `What is the answer for the question:`
345    // - `Q: `
346    // - `answer the following question:`
347    // - `Given the paragraph above, please answer correctly the following question:`
348    #[test]
349    fn test_parse_q() {
350        // randome selected from https://huggingface.co/datasets/BatsResearch/bonito-experiment/viewer/bonito_squadshifts_nyt/train?row=2
351        let completion = 
352            "<|tasktype|>
353        extractive question answering
354        <|context|>
355        Mattingly’s election to baseball’s Hall of Fame in this, his last year of eligibility, is probably not forthcoming (this year’s class of inductees will be announced Tuesday), a melancholy fact. But then, his playing days as a Yankee had something of a melancholy cast. He arrived for a cup of coffee in 1982, a year after the Yankees went to the World Series, and retired in 1995, a year before they returned. And in the last half of his career he was a diminished player, his skills attenuated by the persistent back problems that forced him to quit prematurely at 34, his spirit likely withered by the mortifying shenanigans of the Yankees’ principal owner, George Steinbrenner, and his minions (who once ordered Mattingly fined and benched for not getting a haircut), not to mention the ignominy of a last-place finish in 1990.
356        <|task|>
357         
358        Given the following passage
359        
360        \"{{context}}\",
361        
362        answer the following question. Note that the answer is present within the text.
363        
364        Question: What was Mattingly's last year of eligibility?
365        <|pipe|>
366        1995"
367        ;
368        assert_eq!(
369            parse_q(&completion, "").unwrap(),
370            "What was Mattingly's last year of eligibility?"
371        );
372        assert_eq!(parse_a(&completion).unwrap(), "1995");
373
374        let completion = "<|tasktype|>
375        extractive question answering
376        <|context|>
377        Don Mattingly is the author of one of baseball’s most preposterous statistical anomalies. In 1987, he set the major league record (it has since been tied) for most grand slams in a season — six — and those were the only ones he ever hit. Two of them came during a streak in mid-July when he matched the record for most consecutive games with a home run — eight — actually hitting 10 in eight games. The last one, in Texas against the Rangers, just barely sailed over the wall in left-center field, not exactly the left-handed Mattingly’s power alley. “Holy cow, he did it!” Phil Rizzuto screamed, announcing the feat on TV. “Holy cow, Mattingly is unbelievable.”
378        <|task|>
379         
380        What is the answer for the question: What is the full name of the person who set a record in 1987? from the following article ?
381        
382        {{context}}
383        <|pipe|>
384        Don Mattingly";
385        assert_eq!(parse_q(&completion, "").unwrap(), "What is the full name of the person who set a record in 1987? from the following article ?");
386        assert_eq!(parse_a(&completion).unwrap(), "Don Mattingly");
387
388        let completion = 
389            "<|tasktype|>
390        extractive question answering
391        <|context|>
392        The diverging paths of the two central banks prompted investors to put money into dollars, on the expectation that interest rates in the United States will rise and offer a better return than in Europe, where interest rates are falling. The euro fell to 1.20 against the dollar on Friday, its lowest since June 2010, while the yield, or market interest rate, on German two-year government bonds fell to a new low of minus 0.11 percent. The yield has been below zero since September; investors were willing to effectively pay the German government to keep their money safe. The larger picture is not merely that the dollar is gaining against the euro. Signs that the Fed is getting closer to raising its benchmark interest rate from zero have helped the United States currency to soar against its counterparts in Japan, Britain and in major emerging markets. Against a broad basket of currencies, the dollar has risen more than 13 percent since September to its highest level in almost six years.
393        <|task|>
394         
395        {{context}}
396        
397        Q: What is the yield on German two-year government bonds?
398        
399        A:
400        <|pipe|>
401        minus 0.11 percent";
402        assert_eq!(
403            parse_q(&completion, "").unwrap(),
404            "What is the yield on German two-year government bonds?"
405        );
406        assert_eq!(parse_a(&completion).unwrap(), "minus 0.11 percent");
407
408        let completion = "<|tasktype|>
409        extractive question answering
410        <|context|>
411        As she was dying, Ms. Quick told her daughter that she had lied about the men’s involvement in the fire. Mr. Hale said in an interview on Tuesday that Ms. Quick’s motives to lie may have included liability and an insurance payment that she received (though she testified at the men’s trial that she did not receive such a payment). A fire marshal found what he testified was evidence of arson, but Mr. Hale said evolving fire science meant that the 1980 analysis did not hold up today. Experts’ reports that Mr. Villalobos’s lawyer and the district attorney’s office commissioned as they re-examined the case showed no evidence of arson.
412        <|task|>
413         
414        Given the following context:
415        
416        {{context}}
417        
418        answer the following question:
419        
420        What is the full name of the person who said that Ms. Quick's motives to lie may have included liability and an insurance payment?
421        <|pipe|>
422        Mr. Hale";
423        assert_eq!(parse_q(&completion, "").unwrap(), "What is the full name of the person who said that Ms. Quick's motives to lie may have included liability and an insurance payment?");
424        assert_eq!(parse_a(&completion).unwrap(), "Mr. Hale");
425
426        let completion = "<|tasktype|>
427        extractive question answering
428        <|context|>
429        n armed conflict between Israel and Hamas-led Palestinian militant groups[s] has been taking place chiefly in and around the Gaza Strip since 7 October 2023, when Hamas launched a surprise attack on southern Israel from the Gaza Strip. After clearing Hamas militants from its territory, the Israeli military embarked on an extensive aerial bombardment of the Gaza Strip followed by a large-scale ground invasion beginning on 27 October. Clashes have also occurred in the Israeli-occupied West Bank and with Hezbollah along the Israel–Lebanon border. The fifth war of the Gaza–Israel conflict since 2008, it is part of the broader Israeli–Palestinian conflict, and the most significant military escalation in the region since the Yom Kippur War 50 years earlier.[83]
430        <|task|>
431         2023 was a turbulent year for the Middle East, with several conflicts taking place in different locations. The most notable one was between Israel and Hamas-led Palestinian militant groups. This conflict had its roots in an attack by Hamas on southern Israel from the Gaza Strip on October 7th. In retaliation, Israel launched a massive aerial bombardment of the Gaza Strip on October 27th.
432        
433        Given the paragraph above, please answer correctly the following question: 
434        
435        Which happened first, Israel launched a massive aerial bombardment of the Gaza Strip or Hamas launched a surprise attack on southern Israel?
436        
437        Hint: {{context}}
438        <|pipe|>
439        Hamas launched a surprise attack on southern Israel";
440        assert_eq!(parse_q(&completion, "").unwrap(), "Which happened first, Israel launched a massive aerial bombardment of the Gaza Strip or Hamas launched a surprise attack on southern Israel?");
441        assert_eq!(
442            parse_a(&completion).unwrap(),
443            "Hamas launched a surprise attack on southern Israel"
444        );
445
446        let completion = "<|tasktype|>
447        extractive question answering
448        <|context|>
449        The Alhambra, a medieval Nasrid citadel and palace, is located in Granada. It is one of the most famous monuments of Islamic architecture[7] and one of the most visited tourist sites in Spain.[8][9] Islamic-period influence and Moorish architecture are also preserved in the Albaicín neighborhood and other medieval monuments in the city.[10] The 16th century also saw a flourishing of Mudéjar architecture and Renaissance architecture,[11] followed later by Baroque and Churrigueresque styles.[12][13] The University of Granada has an estimated 47,000 undergraduate students spread over five different campuses in the city. The pomegranate (in Spanish, granada) is the heraldic device of Granada.
450        <|task|>
451         20 students from the University of Chicago visited Granada as an study trip. They stayed in the Albaicin neighborhood. The other group of 20 students visited the medieval monuments in the city. The last group of 20 students visited the Alhambra.
452        
453        Which group learned more about Renaissance architecture?
454        
455        Hint: {{context}}
456        <|pipe|>
457        The Alhambra";
458        assert_eq!(parse_q(&completion, "").unwrap(), "20 students from the University of Chicago visited Granada as an study trip. They stayed in the Albaicin neighborhood. The other group of 20 students visited the medieval monuments in the city. The last group of 20 students visited the Alhambra.
459        
460        Which group learned more about Renaissance architecture?");
461        assert_eq!(parse_a(&completion).unwrap(), "The Alhambra");
462
463        let completion = "<|tasktype|>
464        extractive question answering
465        <|context|>
466        Filesystems in the Kubernetes container provide ephemeral storage, by default. This means that a restart of the pod will wipe out any data on such containers, and therefore, this form of storage is quite limiting in anything but trivial applications. A Kubernetes volume[60] provides persistent storage that exists for the lifetime of the pod itself. This storage can also be used as shared disk space for containers within the pod. Volumes are mounted at specific mount points within the container, which are defined by the pod configuration, and cannot mount onto other volumes or link to other volumes. The same volume can be mounted at different points in the file system tree by different containers.
467        <|task|>
468         2019-05-06T13:47:08.599Z
469        
470        ===
471        
472        Given the background: {{context}}
473        
474        and the situation: John is a cloud engineer. He wanted to try out Kubernetes. To that end, he created two instances, instance A and instance B. Instance A is running on Kubernetes container. But instance B is not running on Kubernetes container. There are some files in both instances. He needs to figure out how they are different.
475        
476        Answer the following question: Which instance would not have ephemeral storage, instance A or instance B?
477        <|pipe|>
478        instance B";
479        assert_eq!(parse_q(&completion, "Filesystems in the Kubernetes container provide ephemeral storage, by default. This means that a restart of the pod will wipe out any data on such containers, and therefore, this form of storage is quite limiting in anything but trivial applications. A Kubernetes volume[60] provides persistent storage that exists for the lifetime of the pod itself. This storage can also be used as shared disk space for containers within the pod. Volumes are mounted at specific mount points within the container, which are defined by the pod configuration, and cannot mount onto other volumes or link to other volumes. The same volume can be mounted at different points in the file system tree by different containers.").unwrap(), "Given the background: Filesystems in the Kubernetes container provide ephemeral storage, by default. This means that a restart of the pod will wipe out any data on such containers, and therefore, this form of storage is quite limiting in anything but trivial applications. A Kubernetes volume[60] provides persistent storage that exists for the lifetime of the pod itself. This storage can also be used as shared disk space for containers within the pod. Volumes are mounted at specific mount points within the container, which are defined by the pod configuration, and cannot mount onto other volumes or link to other volumes. The same volume can be mounted at different points in the file system tree by different containers.\n\n        \n        and the situation: John is a cloud engineer. He wanted to try out Kubernetes. To that end, he created two instances, instance A and instance B. Instance A is running on Kubernetes container. But instance B is not running on Kubernetes container. There are some files in both instances. He needs to figure out how they are different.\n        \n        Answer the following question: Which instance would not have ephemeral storage, instance A or instance B?");
480        assert_eq!(parse_a(&completion).unwrap(), "instance B");
481
482        let completion = "<|tasktype|>
483        extractive question answering
484        <|context|>
485        By doing so, your organization fosters transparency and accountability across all parties involved, thereby minimizing potential conflicts downstream. 2. Implement robust automation tools - Empower developers with self-service capabilities through automated workflows and platforms such as GitOps. Automated deployment pipelines reduce manual intervention, minimize human error, and enable faster iterations. Moreover, incorporating policy-as-code concepts ensures consistent enforcement of organizational standards throughout various stages of the application lifecycle. 3. Encourage knowledge sharing and cross-functional training - Facilitate regular interactions among team members via workshops, hackathons, lunch & learn sessions, or other collaborative initiatives. Cross-pollination of skills helps bridge gaps between different functions and enables better communication channels. Furthermore, empowering individuals to wear multiple hats bolsters understanding of interdependencies among diverse domains, leading to improved empathy and reduced friction points. 4. Measure what matters - Identify key performance indicators (KPIs) aligned with desired business outcomes. Monitor progress against these metrics regularly and adjust course accordingly. Examples include mean time to recovery (MTTR), change failure rate, lead time for changes, deployment frequency, and customer satisfaction indices. Quantifying achievements visibly demonstrates tangible value delivered through adopted methodologies and encourages continuous improvement efforts. 5. Foster a culture of experimentation and learning - Cultivate an environment where taking calculated risks is encouraged, and failures serve as opportunities for growth rather than sources of blame. Support bottom-up innovation efforts by providing psychological safety nets and celebrating small wins along the way. Embracing this mindset fuels curiosity, promotes creative problem solving, and ultimately leads to greater resiliency in navigating complex landscapes. Navigating the delicate dance between control and agility requires careful consideration of marketing and business strategies, particularly regarding internal communications and education efforts surrounding Kubernetes and DevOps adoption. Organizations able to strike this elusive balance stand to reap significant rewards in terms of enhanced efficiency, increased productivity, and sustainable competitive advantage.
486        <|task|>
487          I have a new situation: John is a software developer who works for a multinational tech company. His team has been developing a new product for the past year. Although they have made great progress, there are still some issues with the product. John's team decided to adopt Kubernetes and DevOps practices to improve the product.
488        
489        But I can use this background: {{context}}
490        
491        What is an answer for this question: Will adopting Kubernetes and DevOps help or hinder John's team in improving their product?
492        <|pipe|>
493        help";
494        assert_eq!(parse_q(&completion, "By doing so, your organization fosters transparency and accountability across all parties involved, thereby minimizing potential conflicts downstream. 2. Implement robust automation tools - Empower developers with self-service capabilities through automated workflows and platforms such as GitOps. Automated deployment pipelines reduce manual intervention, minimize human error, and enable faster iterations. Moreover, incorporating policy-as-code concepts ensures consistent enforcement of organizational standards throughout various stages of the application lifecycle. 3. Encourage knowledge sharing and cross-functional training - Facilitate regular interactions among team members via workshops, hackathons, lunch & learn sessions, or other collaborative initiatives. Cross-pollination of skills helps bridge gaps between different functions and enables better communication channels. Furthermore, empowering individuals to wear multiple hats bolsters understanding of interdependencies among diverse domains, leading to improved empathy and reduced friction points. 4. Measure what matters - Identify key performance indicators (KPIs) aligned with desired business outcomes. Monitor progress against these metrics regularly and adjust course accordingly. Examples include mean time to recovery (MTTR), change failure rate, lead time for changes, deployment frequency, and customer satisfaction indices. Quantifying achievements visibly demonstrates tangible value delivered through adopted methodologies and encourages continuous improvement efforts. 5. Foster a culture of experimentation and learning - Cultivate an environment where taking calculated risks is encouraged, and failures serve as opportunities for growth rather than sources of blame. Support bottom-up innovation efforts by providing psychological safety nets and celebrating small wins along the way. Embracing this mindset fuels curiosity, promotes creative problem solving, and ultimately leads to greater resiliency in navigating complex landscapes. Navigating the delicate dance between control and agility requires careful consideration of marketing and business strategies, particularly regarding internal communications and education efforts surrounding Kubernetes and DevOps adoption. Organizations able to strike this elusive balance stand to reap significant rewards in terms of enhanced efficiency, increased productivity, and sustainable competitive advantage.").unwrap(), "I have a new situation: John is a software developer who works for a multinational tech company. His team has been developing a new product for the past year. Although they have made great progress, there are still some issues with the product. John's team decided to adopt Kubernetes and DevOps practices to improve the product.\n        \n        But I can use this background: By doing so, your organization fosters transparency and accountability across all parties involved, thereby minimizing potential conflicts downstream. 2. Implement robust automation tools - Empower developers with self-service capabilities through automated workflows and platforms such as GitOps. Automated deployment pipelines reduce manual intervention, minimize human error, and enable faster iterations. Moreover, incorporating policy-as-code concepts ensures consistent enforcement of organizational standards throughout various stages of the application lifecycle. 3. Encourage knowledge sharing and cross-functional training - Facilitate regular interactions among team members via workshops, hackathons, lunch & learn sessions, or other collaborative initiatives. Cross-pollination of skills helps bridge gaps between different functions and enables better communication channels. Furthermore, empowering individuals to wear multiple hats bolsters understanding of interdependencies among diverse domains, leading to improved empathy and reduced friction points. 4. Measure what matters - Identify key performance indicators (KPIs) aligned with desired business outcomes. Monitor progress against these metrics regularly and adjust course accordingly. Examples include mean time to recovery (MTTR), change failure rate, lead time for changes, deployment frequency, and customer satisfaction indices. Quantifying achievements visibly demonstrates tangible value delivered through adopted methodologies and encourages continuous improvement efforts. 5. Foster a culture of experimentation and learning - Cultivate an environment where taking calculated risks is encouraged, and failures serve as opportunities for growth rather than sources of blame. Support bottom-up innovation efforts by providing psychological safety nets and celebrating small wins along the way. Embracing this mindset fuels curiosity, promotes creative problem solving, and ultimately leads to greater resiliency in navigating complex landscapes. Navigating the delicate dance between control and agility requires careful consideration of marketing and business strategies, particularly regarding internal communications and education efforts surrounding Kubernetes and DevOps adoption. Organizations able to strike this elusive balance stand to reap significant rewards in terms of enhanced efficiency, increased productivity, and sustainable competitive advantage.\n        \n        What is an answer for this question: Will adopting Kubernetes and DevOps help or hinder John's team in improving their product?");
495        assert_eq!(parse_a(&completion).unwrap(), "help");
496    }
497}