Divide-and-Conquer Meets Consensus: Unleashing the Power of Functions in Code Generation

Despite recent progress made by large language models in code generation, they still struggle with programs that meet complex requirements. Recent work utilizes plan-and-solve decomposition to decrease the complexity and leverage self-tests to refine the generated program. Yet, planning deep-inside requirements in advance can be challenging, and the tests need to be accurate to accomplish self-improvement. To this end, we propose FunCoder, a code generation framework incorporating the divide-and-conquer strategy with functional consensus. Specifically, FunCoder recursively branches off sub-functions as smaller goals during code generation, represented by a tree hierarchy. These sub-functions are then composited to attain more complex objectives. Additionally, we designate functions via a consensus formed by identifying similarities in program behavior, mitigating error propagation. FunCoder outperforms state-of-the-art methods by +9.8% on average in HumanEval, MBPP, xCodeEval and MATH with GPT-3.5 and GPT-4. Moreover, our method demonstrates superiority on smaller models: With FunCoder, StableCode-3b surpasses GPT-3.5 by +18.6% and achieves 97.7% of GPT-4's performance on HumanEval. Further analysis reveals that our proposed dynamic function decomposition is capable of handling complex requirements, and the functional consensus prevails over self-testing in correctness evaluation.

Paper

Similar papers

Peer review

Reviewer s7Dq5/10 · confidence 4/52024-06-17

Summary

The paper proposes FunCoder, a code generation framework incorporating the divide-and-conquer strategy with functional consensus. FunCoder recursively branches off sub-functions as smaller goals during code generation, represented by a tree hierarchy. These sub-functions are then composited to attain more complex objectives. Additionally, they use a consensus formed by identifying similarities in program behavior, mitigating error propagation. FunCoder shows great perormance compared to baselines by +9.8% on average in HumanEval, MBPP, xCodeEval and MATH with GPT-3.5 and GPT-4.

Strengths

+ interesting method + impressive experiment and results

Weaknesses

- some important details are missing - lack analysis for cost The paper is commendably clear and the results of the experiments are striking. However, I find that the sections detailing the approach are somewhat brief, which leaves me wanting a deeper understanding of the full method, especially since the study focuses on employing a divide-and-conquer approach for code generation. It would be greatly beneficial if the authors could expand on this strategy. For instance, how does the model determine which functions require further division or are enough simplistic? Are there specific experiments that illustrate this process? Additionally, it would be insightful to know whether the model is designed to recognize dependencies among the subdivided functions and how it integrates these components effectively. Regarding the implementation costs, the approach involves segmenting the program generation into multiple stages using a depth-first search for each sub-program. This intricate process prompts a question about the overall efficiency and resource utilization. I would appreciate if the authors could provide more detailed information on the costs associated with these procedures.

Questions

- How the model decide the functions to be further divided or too simple? Any experiment? - How the conquer works? Does the model aware of the dependency among those sub functions? - What is the cost of each part?

Rating

5

Confidence

4

Soundness

2

Presentation

2

Contribution

2

Limitations

Some limitations have been discussed but it would be better to discuss more on the cost of the FUNCODER and the limitation of divide-and-conquer for hard problems.

Reviewer Ar6t6/10 · confidence 4/52024-07-02

Summary

This paper presents Divide-and-Conquer Meets Consensus -- a prompting scheme for generating complex functional code. In contrast to planning ahead of time, the proposed technique performs planning in smaller steps by decomposing a coding task into smaller sub-tasks recursively and solving them when they are simple enough. The evaluation shows that the technique can significantly outperform prior arts and works for both proprietary models and smaller open models.

Strengths

1. This paper targets the important problem of code generation for complex coding tasks which is right now the bottleneck of the code generation domain as simple coding benchmarks have been saturated. 2. The overall framework of the technique is novel and beautiful, borrowing insights from the classical concept of the divide-and-conquer principle. 3. This paper provides a number of interesting insights beyond the base experimental results, e.g., in self-testing it is challenging to obtain both valid code and valid tests.

Weaknesses

1. There is a flaw in the design of functionality similarity. Authors claim in L104 that they sample inputs from the input domain of the function, namely D(f). First, it is non-trivial to infer D(f). While simple type analysis is applicable, oftentimes the pre-conditions of the function can go beyond type constraints. For example, the pre-condition asserts the input sequence is sorted when doing code generation for binary search. Second, it is challenging to accurately infer such pre-conditions, and inputs violating such pre-conditions often manifest undefined behaviors of function candidates, falsifying functionality-similarly candidates. For example, in the EvalPlus paper, these conditions are manually specified to ensure the soundness of test input generation. In summary, the equivalence-modulo-inputs idea requires knowing the accurate input domain and designing corresponding input samplers, which are oversimplified in this paper. 2. Back to the high-level framework, it is unclear why functionality consensus would work in the first place. Functionality consensus selects the most common functor candidate, but commonality may not necessarily correlate with correctness in code generation. Correct samples can even be exceptional in sampling when the task is challenging to the LLM. 3. The diversity of studied models is a bit limited. It would be helpful to run Divide-Conquer on more open models such as StarCoder2. Minor suggestions: 1. L97 "A program specifies its functionality (or behavior) through the control flow...": This is not accurate as control flow is just a partial representation of code semantics. For example, `a + b` and `a - b` share the same control flow (i.e., no control flow) but stand for completely different semantics.

Questions

1. Can you exemplify "cascading errors" in Section 2.2? Can you also better explain why sampling multiple functions helps mitigate such errors? 2. The technique is motivated to solve complicated coding tasks. I wonder if the selection of benchmarks can really exercise the core part of the technique, i.e., resolving complex code generation tasks. 3. When computing the token usage, did you include tokens of unused samples when computing "functionality similarity"? Can you also provide more statistics such as the medium token consumption in case the average number is biased by simple tasks? Overall the presented token consumption in Table 3 is much smaller than I expected according to the large prompts shown in the Appendix (and these will be called multiple times). 4. How's the token usage compared to other baselines? 5. Is the technique single-turn or multi-turn when being implemented for evaluation?

Rating

6

Confidence

4

Soundness

2

Presentation

3

Contribution

3

Limitations

Social impact wise this paper is fine. For technical limitations, they are reflected in the weaknesses section.

Reviewer LV7h6/10 · confidence 4/52024-07-08

Summary

The paper presents FuncCoder, a novel coding framework designed to enhance code generation by incorporating a divide-and-conquer strategy with functional consensus. FuncCoder addresses the limitations of existing methods that struggle with complex programming tasks by recursively breaking down problems into smaller sub-functions, which are then hierarchically organized and recomposed to achieve more complex goals. The functional consensus mechanism mitigates error propagation by selecting functions that exhibit similar behaviors. Experimental results show that FuncCoder outperforms state-of-the-art methods, such as Parcel and Reflexion, on various benchmarks, including HumanEval, MBPP, and xCodeEval, and demonstrates its effectiveness across different language models like GPT-3.5, GPT-4, as well as smaller models such as StableCode3b. The framework's ability to dynamically decompose and compose functions enables superior performance in handling complex coding requirements and mathematical reasoning tasks.

Strengths

+ The paper proposes FunCoder, a plan-and-solve coding LLM optimized with recursively divide-and-conquer. The design of FunCoder is generally reasonable and the methodologies are well explained and motivated. + Besides outperforming SOTA baselines, such as Parcel and Reflexion based on GPT-based models, it is impressive how FunCoder significantly improve the small LLMs' performance. + The paper performs in-depth analysis and ablation study to illustrate FunCoder's effectiveness and justify different design choices.

Weaknesses

While FunCoder demonstrates impressive performance in handling well-defined programming challenges, there is a practical concern regarding the token length of the trajectory. The recursive decomposition of tasks into sub-functions inherently leads to the generation of numerous function headers, bodies, and documentations, which can significantly inflate the token count. As reported by Table-3, the average token length is ~5.5k, and I am curious about the median and the maximum tokens required to solve HumanEval problem. This becomes concerning when dealing with more intricate and interconnected coding requirements. As each layer of decomposition adds to the overall length, the token usage can escalate rapidly, leading to inefficiencies and increased computational costs. The empirical data shows that while FunCoder performs well on self-contained coding benchmarks, the token length could become a limiting factor for more complex problems, potentially offsetting the advantages gained through the divide-and-conquer approach. This exponential growth in token length necessitates careful consideration and optimization to ensure that FunCoder remains scalable and efficient for a broader range of coding tasks.

Questions

+ Why do the authors report different methods for GPT-3.5 and GPT-4 in Table-1? Aren't these approaches generalizable to all GPT-based models through API? I would suggest the authors to add back missing baselines for both models. A similar question presents in Table-4 + In Table-4, why do the authors choose CoT or self-refine as the main baseline while no more comparing with Parcel? + Why do the authors choose not to disclose their code during the submission phase?

Rating

6

Confidence

4

Soundness

3

Presentation

3

Contribution

3

Limitations

The paper discusses the limitation in Section 5.

Reviewer 8URc7/10 · confidence 3/52024-07-10

Summary

The author applies divide-and-conquer methods to code generation problems with Large Language Models (LLMs). A problem is divided into subproblems recursively; that is, the function that solves the problem is generated in a top-down manner. Given the parent function, the LLM is prompted to implement it using child functions, which are yet to be implemented. Then, it recursively implements the child functions. There are two key components that make this method work well: 1. A two-pass generation approach: When generating a function f, the first pass generates the function/plans without child functions being implemented yet. The second pass occurs when the children functions are implemented, conditioning on the children functions and regenerating the parent functions again. This is to overcome potential problems that may arise when parent functions are generated before child functions are concretely implemented. 2. Consensus via multiple sampling: Each time a function is regenerated in the second pass, multiple programs are sampled, and a consensus of the samples is used to generate the final program. The consensus is determined by selecting the program that exhibits the most similar input-output behavior to other functions. Experimental results show it improves performance effectively on HumanEval, MBPP, xCodeEval, and MATH benchmarks, and remarkable 94.5% results on HumanEval with GPT4.

Strengths

* The method is conceptually very clean and effective empirically, as shown on various benchmarks including three code generation tasks and math-solving tasks. * Extensive experiments and ablation studies are conducted to show the effectiveness of the method. * The results also show that the method is effective not just on large closed-source models, but also on smaller open models such as LLaMA 3 8B and StableCode 3B. This contributes to the reproducibility of the method.

Weaknesses

* The idea of decomposing the problem into subproblems and solving them recursively with an LLM is not entirely new. * The consensus method, which aims to select top programs from a set of samples using similarity, is different but similar to the AlphaCode approach. It would be interesting to see a comparison of selecting the top programs using majority voting on the input/output as in AlphaCode instead of calculating the similarity.

Questions

* On average, how many decomposition levels are used when solving the code generation tasks? * Are the Standard and CodeT prompts used in the experiments the ones shown in Appendix C.1? Is this type of decomposition prompting also better for the Standard and CodeT methods? * How does the consensus method compare to other self-consistency or AlphaCode-like majority clustering methods? * In the abstract and line 167, it is said that GPT4 performance on HumanEval is about 97% but I can't find that number in Table 1. Is it mentioned else where?

Rating

7

Confidence

3

Soundness

3

Presentation

3

Contribution

3

Limitations

Yes, one limitation that it is not suitable for software engineering/ open coding problems is discussed.

Reviewer s7Dq2024-08-09

Thank you for the detailed rebuttal and the efforts made to clarify the cost analysis in your paper. However, I still have some concerns regarding the logic and assumptions underlying this analysis. The analysis of token cost appears to assume an ideal scenario where no failures occur. Additionally, the new data presented in the rebuttal seems to mirror Table 3 of the paper(ablation study). We would like to see the analysis results of Table 1 or 2(compared to the SOTA). In a naive program, the standard is a -> BC, and yours is A, [B, C] (follow your notations). We assume the divide and conquer is perfectly gained, and the pass rate is just the success rate. The best performance of FUNCODER is 94.5. Then, your success rate to derive b->B and c->C should be increased to the square root of 0.945, which means 0.972. When the program becomes much more complex, the requirement of success rate for each divided subprogram is further increased. I think there should be some design and cost to increase the performance, even if the divided programs are simpler than the original ones. However, from the rebuttal, it seems most parts depend on the LLM for program generation and divide-conquer, which means the error will increase when the program becomes more complex. I am willing to consider increasing my score if we could address these questions.

Authorsrebuttal2024-08-11

We thank you again for taking your time to read our responses and provide suggestions. > **1. The analysis of token cost appears to assume an ideal scenario where no failures occur.** Indeed, in the analysis of general response, we simplified the situations and ignored the the situations where the LLMs make a mistake. However, in token cost results (Table 3, 11 and in our response) we have **always included** token usage for retries to ensure fair comparison, and we argue that this situation may be trivial to consider. Failures that cause retries can rarely happen in FunCoder -- they happen if and only if no code can be extracted from the responses' Markdown blocks, or that the code was syntactically incorrect. We provide additional statistic results in the table below, which shows a relatively low failure rate even in complex questions (MATH or xCodeEval). | Dataset | Pass@1 | failed to parse / all LLM calls | |---|---|---| | HumanEval | 85.4 | 0.10% | | MBPP | 78.5 | 0.31% | | xCodeEval | 31.4 | 1.68% | | MATH | 54.0 | 2.10% | > **2. We would like to see the analysis results of Table 1 or 2 (compared to the SOTA).** We report token consumption data for some of the fields in Table 1 and Table 4, regarding GPT-3.5 and SOTA methods, in the table below. Some of the cells are missing data since some methods were not open-source and did not report detailed token usage. | Dataset | Method | Pass@1 | min tks | max tks | mean tks | med tks | |---|---|---|---|---|---|---| | HumanEval | Standard | 68.3 | 648 | 1477 | 886.7 | 861 | | | CodeT | 81.1 | 2298 | 9645 | 4479.1 | 4166 | | | Reflexion | 69.5 | 416 | 4906 | 1416.1 | 754 | | | LDB (Reported prev SOTA) | 82.9 | - | - | ~23000 | - | | | FUNCODER | 85.4 | 3015 | 13850 | 5402.0 | 5166 | | xCodeEval | Standard | 20.2 | 1051 | 3343 | 1599.5 | 1530 | | | CodeT (prev SOTA) | 23.2 | 2264 | 9245 | 3937.4 | 3733 | | | Reflexion | 20.6 | 2977 | 1003222 | 401767.3 | 328591 | | | FUNCODER | 31.4 | 4883 | 53225 | 10559.7 | 8927 | | MATH | Standard | 62.2 | 551 | 5867 | 953.0 | 835 | | | FUNCODER | 76.8 | 2622 | 30139 | 7075.5 | 5666.5 | > **3. Then, your success rate to derive b->B and c->C should be increased to the square root of 0.945, which means 0.972. When the program becomes much more complex, the requirement of success rate for each divided subprogram is further increased.** **Accumulated errors in FunCoder also occur in Standard**, where generating all functions (ABC) all at once would have a higher error rate than generating one at a time (A, B, C). Note that this metaphor may not be exact since 94.5% acc is an average of all problems, where different problems are decomposed into different depths. However, we follow this metaphor and continue to show why FunCoder works better than other methods. Here success rate of *Standard* on a single function is $\sqrt{82.9}=91.0$. On a harder dataset where problems are decomposed to 10 levels of functions on average, *Standard*'s overall accuracy will be $91.0^{10}=38.9$, while FunCoder still keeps $97.2^{10}=79.3$. Results on xCodeEval dataset shows that FunCoder gets greater improvements on harder problems compared to simple problems. But of course, the analysis we just made was based on a simple assumption and does not reflect reality. > **4. I think there should be some design and cost to increase the performance, even if the divided programs are simpler than the original ones.** We designed FunCoder under the consideration of complex problem performance, and have made visible progress. Particularly, our method: 1. **Divide** dynamically decomposes problems into simpler subproblems, making them easier to solve. The Divide stage always considers just one layer of problem at a time, thus can keep the model in context, reducing ambiguity and complexity caused by extra-long code. For instance, the problem A-B-C-D requires all these functions to be in context in *Standard*, while ours only need 2 for each of the 4 calls. 2. **Conquer** enables bottom-up generation through re-composing simple functions into a complex solution to a complex problem. This mitigates the issue where Divide cannot see the subfunctions while generating parent functions, making function dependencies more robust. (Note that LLMs are autoregressive models, so while *Standard* generates ABC, when A is being generated B,C aren't there yet. This could cause *Standard* to mis-invoke B or C from A in this implementation.) 3. **Functional consensus** verifies every function starting from the leaves. Through sampling and voting, incidental errors and cascading errors may be reduced and thus the accuracy could be improved. Before our method, self-test was widely used for verifying programs, and now FunCoder manages to achieve higher performance with the same level of token complexity. We further note that Divide, Conquer and Consensus may be used together, and that using them in conjunction will further raise the accuracy on complex problems.

Reviewer s7Dq2024-08-11

Thank you for your detailed response. I am generally satisfied with the clarifications provided; however, I have reservations regarding point 3. Traditional LLMs just generate the whole code. Your techniques are generated in a divide-conquer way, which means the LLM needs to understand the code dependency and generate multiple times for each sub-problem considering the context. The sub-problems may be easier than the origin problems, which means the overall success rate (94.5) and the success rate for sub-problems (97.2) would be different. More complex problems require higher accuracy on sub-problems (~100%). Does that mean that in your experiment, for simple sub-problems, the LLM can reach almost 100% accuracy? Additional experiments could be highly beneficial to solidify the claims of your technique’s effectiveness. Specifically, experiments that vary the depth of sub-problem generation (e.g., restricting the LLM to generate a depth of 2 or 3 programs) could provide valuable insights into how the structure and depth of problem decomposition affect the overall pass rate. I've adjusted my score to reflect my appreciation of the responses you have provided.

Authorsrebuttal2024-08-12

We sincerely thank you for the follow-up discussion and the rating update. For accuracy on simple sub-problems, we hypothesize that well-trained LLMs can solve them well (compared to complex sub-problems). But since this needs human labeling for all LLM outputs, which is beyond our available man-power, we might not include statistics for this issue. With that said, we hope that future research may look into this and investigate further. While there may be a slight possibility of losing accuracy forcing the LLM to decompose a simple problem (when the LLM is not trained to decompose such problems), or vice versa, conducting experiments that enforce program depth during generation is actually a very interesting idea. Such experiments may provide more insights to how complexity correlates with functional decomposition, and may lead to more promising ways to reliable code generation. So we welcome future work that proposes new, faithful methods to control this function decomposition depth.

Reviewer Ar6t2024-08-12

Thanks for the reply!

Overall I am satisfied with the authors' responses. Weaknesses 3 and 4 should be easily addressable and I look forward to seeing more models being compared. While weaknesses 1&2 are not resolved due to their challenges, I suggest at least discussing them as limitations of the technique in the revision and calling for further research. Specifically, I feel the concern of W1 is a bit outstanding. Probably the only way to address it right now is to add program contracts via human experts (for example, contracts are added manually in the EvalPlus paper for test-case reliability) or LLMs; some weak pre-condition is also better than nothing even if they cannot be strictly verified. I'm happy to increase by rating to 6.

Authorsrebuttal2024-08-12

We sincerely thank you for your response and your rating update. We fully agree with you that weakness 1 & 2 should be at least discussed in the limitations section, and we will add them in our next revision. We look forward to future research that investigates these weaknesses and, better yet, be accompanied with theoretical analysis.

Reviewer LV7h2024-08-12

Thanks for the authors response. It mostly makes sense, though I have concerns why the minimum working code for replication requires **months** to release while the authors acknowledge the methods are relatively straightforward. I would like to see some brief explanations of what are the most time-consuming part for code release and the main difficulty of implementing the current agentic system.

Authorsrebuttal2024-08-13

We thank you for your response and again apologize for causing confusion regarding our code. To put it honestly, we were quite busy with other things on our hands, so didn't have enough time to polish our code. But we reassure you that the method **and the implementation** are still straightforward, and that replicating this work from scratch needn't two months time (far less than that). As is also discussed in the *Limitations and Social Impact* section that directly running code generated by LLMs can be risky. Although our current version of Code Interpreter Sandbox works and could prevent the machine from many known attacks, we are actively looking for more promising means of protection, lest our code causes problems when it goes public. Comments and suggestions on how the code should be open-sourced are also super welcomed.

Program Chairsdecision2024-09-25

Decision

Accept (oral)

© 2026 NYSGPT2525 LLC