최근 동적 타입 언어나 간결한 언어가 정적 타입 언어보다 LLM 토큰을 덜 소모해 효율적이라는 주장이 화제입니다. 하지만 기존 벤치마크는 단순한 문제에만 국한되거나 테스트 설계에 오류가 있어 신뢰하기 어렵다는 비판이 제기됩니다. 실제 복잡한 작업에서는 이러한 토크 효율성의 이점이 희석될 수 있으며, 평가 방식의 개선이 필요합니다.
번역된 본문
꽤 널리 인용되는 이 게시물(어쨌든 계속 인용되는 것을 봅니다)은 동적 언어 및/또는 것을 더 간결하게 표현하는 언어가 토큰 효율성이 더 높다고 제안합니다. 이 게시물이 LLM 검색 결과에도 반영될 만큼 충분히 인용되는 것 같습니다. 예를 들어, "동적 대 정적 언어 토큰 비용"(따옴표 없이)을 검색했을 때 구글 AI 요약은 명시적인 타입 선언을 생략하면 코드가 더 간결해지기 때문에 동적 타입 언어가 전통적인 정적 타입 언어보다 일반적으로 LLM 토큰 비용이 낮다는 것으로 시작했습니다. 구글 AI는 동일한 게시물을 인용했는데, 이는 일부 간결한 동적 언어가 Rust, Go, C++ 등과 같은 정적 언어보다 토큰 비용이 약 1/2에서 1/3 수준이라는 것을 시사합니다. 저자는 "내가 비교한 언어 중 토큰 효율성이 가장 낮은 C언어와 가장 높은 Clojure 사이에는 2.6배의 매우 의미 있는 격차가 있었다"고 말합니다. 그리고 나중에 J 언어를 시도해 보며, "평균 70토큰으로 압도적이며, 이는 Clojure(109토큰)의 절반에 불과하다. 배열 언어는 특이한 기호 집합을 피하면 극도로 토큰 효율적일 수 있다"고 말합니다. 토큰 효율성이 핵심 동력으로 판명된다면, 이는 언어가 진화하는 매우 흥미로운 방식일 수 있습니다. 제가 돌아다니며 발견한 다른 동적 대 정적 언어 토큰 비교 또한 동일한 결론을 지지합니다. 이것을 벤치마킹, 평가 및 실험 설계에 대한 연재 글의 8부로 취급하고 싶다면, 링크를 클릭하여 더 읽기 전에 평가 문제에 대해 생각해 볼 수 있습니다.
직접 평가를 실행하지 않고 알 수 있는 첫 번째 실험의 문제점은 앞서 인용한 문장에서 알 수 있듯이 문제가 너무 단순하다는 것입니다. J 언어로 70토큰, Clojure로 109토큰으로 해결할 수 있는 문제는 전혀 문제가 아닙니다(저자는 Rosetta Code를 사용했습니다). 원시적인 방식과 우리의 평가를 비교한 다른 사례에서 살펴봤듯이, 대부분의 작업이 정답을 출력하는 데 집중되는 단순한 문제와 약간의 "진짜 작업"이 필요한 덜 단순한 문제에서는 매우 다른 결과를 얻을 수 있습니다. 원시적인 방식에서 주장되고 재현된 큰 이득은 단 몇 개의 토큰 이상이 필요한 문제를 살펴보기 시작하면 사라집니다. 일반적으로 단순한 작업에서의 성능은 일반화되지 않습니다. 두 번째 링크의 문제는 조금 더 미묘해서 대부분 부록으로 미루겠지만, 테스트 중 하나가 존재하지 않는 잘못된 경로를 실행하여 테스트가 실패하는 것과 같은 문제를 포함합니다. 그 이후의 에이전트 중 하나가 존재하지 않는 경로를 자신의 실행 파일에 대한 심볼릭 링크로 만드는데, 이는 해당 케이스에서는 작동하지만 이후의 모든 테스트가 올바른 실행 파일 대신 그 에이전트의 실행 파일을 실행하게 만듭니다. 저자는 Rust에 몇 가지 실패가 있었다는 것이 무엇을 의미하는지에 대해 결론을 내리려고 시도하지만, 이는 단지 Go 에이전트가 해당 손상된 테스트에 대한 모든 채점을 Go 실행 파일로 심볼릭 링크하기 전에 Rust에 대한 채점이 실행되었음을 의미할 뿐입니다.
이러한 평가에 의존하는 대신, 우리는 우리만의 몇 가지 평가를 실행해 볼 수 있습니다. 이러한 평가와 저번 평가 연습에서 논의된 내용에서 알 수 있듯이, 평가를 만든 사람이 생각하는 것을 말해주지 않는 평가를 만드는 것은 매우 쉽습니다. 의심할 여지 없이 이 평가들 역시 예외가 아니며 결함이 있을 것입니다(자세한 내용은 아래 부록 참조). 사물에 대한 직관을 구축하는 방법으로, 저는 결과를 살펴보기 전에 미리 추측을 짚어보는 것을 좋아합니다. 친구들과 미리 공유한 몇 가지 추측은 다음과 같습니다. 높은 신뢰도(95%): 전반적인 동적 대 정적 언어 주장은 유지되지 않을 것이다. 위에서 명시된 이유로 인해: 이것은 문제가 커질수록 결과가 기껏해야 희석되는 원시적인 평가와 유사하게 느껴집니다. 낮은 신뢰도(60%): 극단적인 노력(ultra effort)에서 정적 언어는 동적 언어보다 약간 더 나을 것이다. 극단적인 노력에서 테스트 하네스가 모델에게 더 빨리 피드백을 제공하여 정확성이나 효율성에 어떤 이점을 가져다줄 것이라는 매우 약한 신뢰도를 가집니다만, 모든 종류의 경우에 그렇지 않을 수도 있다는 것도 합리적으로 보입니다.
This somewhat widely cited post (I keep seeing it cited, anyway) suggests that dynamic languages and/or languages that represent things more concisely are more token efficient. It seems to be cited enough that LLM search results agree. For example, when I searched for "dynamic vs static language token cost" (no quotes), Google's AI summary opened with Dynamically typed languages generally have a lower LLM token cost than traditional statically typed languages because omitting explicit type declarations makes the code more compact. Google's AI cited the same post, which suggests that some concise dynamic languages have maybe 1/2 to 1/3 the token cost of static languages like Rust, Go, C++, etc. The author says There was a very meaningful gap of 2.6x between C (the least token efficient language I compared) and Clojure (the most efficient). And then they later tried J, saying It dominates at just 70 tokens average, nearly half of Clojure (109 tokens). Array languages can be extremely token-efficient when they avoid exotic symbol sets. If token efficiency turns out to be a key driver, this is perhaps a very interesting way for languages to evolve. The other dynamic vs. static language token comparison I've found floating around is this one , which supports the same conclusion. If you want to treat this as part 8 of this series of exercises on benchmarking, evals, and experimental design , you can click through to the links and think about eval issues before reading further. Without running our own eval, one problem the first experiment has is that the problems are trivial, which we can see from quote above; a problem that can be solved in 70 tokens in J and 109 in Clojure isn't much of a problem at all (the author used Rosetta Code). As we saw when we looked at other evals of caveman mode vs. our own evals , you can get very different results from trivial problems where most of the work is in printing out an answer vs. slightly less trivial problems that actually require some amount of "real work"; the big gains claimed by caveman mode and shown in replications go away when you start looking at problems that take more than just a few tokens. In general, performance on trivial tasks doesn't generalize. The issues in the second link are a little more subtle, so we'll defer most of them to an appendix, but they include issues like one of the tests executing the wrong path (which doesn't exist), causing a test to fail. One of the later agents then symlinks the non-existent path to its own executable, which works for that case, but also causes every later test to run that one agent's executable instead of the correct executable. The author tries to draw conclusions about what it means that Rust had some failures, but all it means is that scoring for Rust ran before the Go agent symlinked all scoring on that broken test to the Go executable. Instead of relying on these evals, we can try running some of our own evals. As we can see from these evals as well as the evals discussed in our last exercises on evals , it's very easy to make an eval that doesn't say what the creator of the eval seems to think it's saying. No doubt these evals will not be an exception to this and will be flawed (see appendix below for more details). As a way to build my intuition about things, I like to pre-register guesses before looking at results 1 . Some things I pre-registered with friends were: High confidence (95%): the overall dynamic vs. static language claim won't hold For reasons stated above: this feels analogous to the caveman eval, where the result will, at best, get diluted as the problem gets larger Low confidence (60%): static languages will be somewhat better than dynamic at ultra effort Very weak confidence that, at ultra effort, the harness will get feedback to the model more quickly and this will result in some kind of benefit for either correctness or efficiency, but it would also seem reasonable for this to not be the case for all kinds of reasons, e.g., I've noticed that codex, when invoking the Rust compiler, very often makes the exact same error and then has to fix it; perhaps this kind of thing dwarfs things like a hypothetical faster feedback cycle High confidence (98%): the "weird" language supremacy of something like J won't hold Same reasoning as the overall static vs. dynamic claim, with the additional thought that AI labs are going to have much less (and possibly zero) synthetic data RL env effort on obscure languages Zstd For the first eval, I tried giving agents the zstd RFC (plus errata) and telling them to implement a complete zstd decoder (agents are stuck in a container without internet access). The tests were not given to agents. For something with the surface area of zstd, it's not really reasonable to expect that the tests cover every possible case. For example, even though zstd is a fairly well-tested piece of software, I once found a data corruption bug in zstd . The test suite isn't intended to find extreme corner cases that might be lurking for years and is instead intended to check various cases that can "easily" be derived from the RFC that should work. Below, the x-axis is cost and the y-axis is correctness score (up and to the left is better / down and to the right is worse); average result on medium and ultra efforts with GPT-5.6 Sol. If we only look at medium (and ignore the fact that results often wildly differ on different tasks), we might come to a conclusion like the Alderson evaluation, that dynamic languages are more efficient and better when using LLMs because (ignoring relatively obscure languages) the cluster of dynamic languages lands up and to the left of the cluster of static languages (we used Alderson's color-coding for static vs. dynamic to make it easy to compare at a glance). But if we look at ultra effort, the results are quite mixed, with a couple static languages doing the best, with more static than dynamic languages among the better results. The graphs below also have a toggle to convert the x-axis to time instead of cost. The mame/ai-coding-lang-bench noted that it's valuable to get results more quickly (I personally don't find this to be the case because results take long enough that I multitask instead of waiting), so we can also look at that. Similarly, we observe that neither language type dominates the other although, at medium effort on this particular task, the best dynamic language results are once again better than the best static language results (though, once again, they're fairly close). We can observe that, just like when we compared completely trivial caveman mode evals to a less trivial caveman mode eval, the very strong relationships that held in the trivial evals don't generalize to this larger case. As was the case there, the extreme ratios in performance go away in these larger evals, except in cases where we might expect poor performance, such as when using assembly (which would be significantly more time consuming and difficult for a human) and when using relatively obscure languages where we might not expect that AI labs are expending effort generating synthetic RL environment data. Note that this is the opposite of what the 1st eval found when it suggested that very dense languages like J would make sense for efficiency reasons. Perhaps using an obscure (and "weird") language can make sense if you have a very large budget and you can train or fine-tune a model to be effective for your pet language, but if you're a normal user of LLMs, it seems like sticking with a mainstream language is likely a better bet than using an obscure dense language. And it turns out that if we plot language popularity vs. performance on this eval (not shown), we observe a weak to moderate positive correlation where more popular languages end up with more correct as well as cheaper solutions. As we previously noted, very closely related evals can give substantially different results. For example, we saw signifi