Explaining Lineage in DAX
In DAX, lineage is an important concept, and it is vital to understand how to work with and manipulate it. As I did in past articles, I will use DAX queries to explain this concept and its effects. I start with a simple query to get the order count for the product of the brand “Adventure Works”: EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,"Order Count", [Online Order Count] ) ,'Product'[BrandName] = "Adventure Works" ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] This is an extract of the result from the query: This query returns 180 rows. Keep it in mind, as it will be important later on. Next, I will introduce a filter for a specific month and show the lineage’s role
In DAX, lineage is an important concept, and it is vital to understand how to work with and manipulate it. As I did in past articles, I will use DAX queries to explain this concept and its effects. I start with a simple query to get the order count for the product of the brand “Adventure Works”: EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,"Order Count", [Online Order Count] ) ,'Product'[BrandName] = "Adventure Works" ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] This is an extract of the result from the query: This query returns 180 rows. Keep it in mind, as it will be important later on. Next, I will introduce a filter for a specific month and show the lineage’s role
. I will add a filter for April 2026: DEFINE VAR YearMonthFilter = 202604 EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,"Order Count", [Online Order Count] ) ,'Product'[BrandName] = "Adventure Works" ,'Date'[MonthKey] = YearMonthFilter ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] In this case, I define a variable and set the value to 202604. Next, I add it as a filter to the CALCULATETABLE() function. Nothing special so far. In this case, the lineage is not important, as a scalar value sets the filter. But we can set a lineage by using the TREATAS() function: DEFINE VAR YearMonthFilter = TREATAS({ 202604 }, 'Date'[MonthKey]) EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,"Order Count", [Online Order Count] ) ,'Product'[BrandName] = "Adventure Works" ,YearMonthFilter ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] As you can see, the introduction of TREATAS() allows us to pass the variable as a filter. CALCULATETABLE() uses the lineage set by TREATAS() as a filter on the column ‘Date'[MonthKey]. The result doesn’t change, but the query is simpler, as I don’t need to pass the condition as “column equals the filter-value”. In fact, Power BI uses this form all the time when it passes filters set in a report to the semantic model. But it does differently: It defines variables, sets the lineage and adds all filters directly to SUMMARIZECOLUMNS() : DEFINE VAR YearMonthFilter = TREATAS({ 202604 }, 'Date'[MonthKey]) VAR SelectedBrand = TREATAS( { "Adventure Works" }, 'Product'[BrandName]) EVALUATE SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,YearMonthFilter ,SelectedBrand ,"Order Count", [Online Order Count] ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] Clearing the lineage You might encounter situations where you need to clear the lineage. The method for doing it varies depending on whether you have a single or multiple values as a filter. For example, look at the following code, where I use VALUE() to remove the lineage on the previous expression: DEFINE VAR YearMonthFilter = TREATAS({ 202604 }, 'Date'[MonthKey]) VAR YearMonthFilter_cleared = VALUE(YearMonthFilter) EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,"Order Count", [Online Order Count] ) ,'Product'[BrandName] = "Adventure Works" ,YearMonthFilter_cleared ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] This is the error delivered by Power BI: The engine cannot work with the filter in line 71 because it no longer has lineage. It will work in this form: DEFINE VAR YearMonthFilter = TREATAS({ 202604 }, 'Date'[MonthKey]) VAR YearMonthFilter_cleared = VALUE(YearMonthFilter) EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,"Order Count", [Online Order Count] ) ,'Product'[BrandName] = "Adventure Works" ,'Date'[MonthKey] = YearMonthFilter_cleared ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] As you can see here, the query returns the same result as before: Notice the change of the filter argument in line 91. But there is a simpler way of clearing the lineage when working with measures. Look at the following query with the Measure [Order Count
full year], which calculates the order count for the entire year: DEFINE MEASURE 'All Measures'[Order Count full year] = VAR SelYear = TREATAS({ SELECTEDVALUE('Date'[Year]) }, 'Date'[Year]) RETURN CALCULATE([Online Order Count] ,REMOVEFILTERS('Date') ,SelYear ) EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,"Order Count", [Online Order Count] ,"Order Count full year", [Order Count full year] ) ,'Product'[BrandName] = "Adventure Works" ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] This is an extract of the result: Now I add a scalar value to the variable: DEFINE MEASURE 'All Measures'[Order Count full year] = VAR SelYear = TREATAS({ SELECTEDVALUE('Date'[Year]) }, 'Date'[Year]) VAR SelYear_Plus1 = SelYear + 0 RETURN CALCULATE([Online Order Count] ,REMOVEFILTERS('Date') ) EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,"Order Count", [Online Order Count] ,"Order Count full year", [Order Count full year] ) ,'Product'[BrandName] = "Adventure Works" ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] This operation clears the lineage, and the measure no longer works: What I can still do is use an equal filter to get the previous result: DEFINE MEASURE 'All Measures'[Order Count full year] = VAR SelYear = TREATAS({ SELECTEDVALUE('Date'[Year]) }, 'Date'[Year]) VAR SelYear_Plus1 = SelYear + 0 RETURN CALCULATE([Online Order Count] ,REMOVEFILTERS('Date') ,'Date'[Year] = SelYear_Plus1 ) EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,"Order Count", [Online Order Count] ,"Order Count full year", [Order Count full year] ) ,'Product'[BrandName] = "Adventure Works" ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] Now I get the same result as before: And now, let’s use multiple values as a filter. For example, two months: DEFINE VAR YearMonthFilter = TREATAS({ 202604, 202605 }, 'Date'[MonthKey]) EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,"Order Count", [Online Order Count] ) ,'Product'[BrandName] = "Adventure Works" ,YearMonthFilter ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] Here is the result of this query: One way to remove the lineage of a variable with multiple values is to use SUMMARIZECOLUMNS() : DEFINE VAR YearMonthFilter = TREATAS({ 202604, 202605 }, 'Date'[MonthKey]) VAR YearMonthFilter_cleared = SUMMARIZECOLUMNS(YearMonthFilter) EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,"Order Count", [Online Order Count] ) ,'Product'[BrandName] = "Adventure Works" ,YearMonthFilter_cleared ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] Unfortunately, this method removes the filter altogether, and all months are returned in 180 rows (The same number of rows as with the initial query): Technically, the lineage is not cleared because the query still works, but the month filter is removed. But when you try using the variable “YearMonthFilter_cleared” with an IN operator, it doesn’t work anymore: In this context, I tried other functions, like DISTINCT() and VALUES() . While DISTINCT() had no effect, VALUES() has. For example, while this query doesn’t work: DEFINE VAR YearMonthFilter =
TREATAS({ 202604, 202605 }, 'Date'[MonthKey]) VAR YearMonthFilter_cleared = VALUES(YearMonthFilter) EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,"Order Count", [Online Order Count] ) ,'Product'[BrandName] = "Adventure Works" ,YearMonthFilter_cleared ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] Here is the error message: This works when using an IN operator, which indicates that the lineage is cleared when using VALUES(): DEFINE VAR YearMonthFilter = TREATAS({ 202604, 202605 }, 'Date'[MonthKey]) VAR YearMonthFilter_cleared = VALUES(YearMonthFilter) EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[MonthShortName] ,'Date'[MonthKey] ,'Product'[ProductCategoryName] ,"Order Count", [Online Order Count] ) ,'Product'[BrandName] = "Adventure Works" ,'Date'[MonthKey] IN YearMonthFilter ) ORDER BY 'Date'[MonthKey] ,'Product'[ProductCategoryName] Here is the result of the query: The documentation for VALUES() states that this function requires a table or column reference. But this behaviour shows that it depends on how the variable is used in the query. As the variable has a lineage set, VALUES() accept it as a column reference. Next, let’s change how we apply a filter by manipulating the lineage. I want to create a report showing all online orders by country, along with the orders served by stores in each country. For example, I have 68 customer orders from Germany in April 2026. I want to see how many orders have been served by stores in that country, if any. Something like this: I can do it by working with a variable: DEFINE MEASURE 'All Measures'[Orders served from Country] = VAR SelCountry = SELECTEDVALUE('Customer'[RegionCountryName]) RETURN CALCULATE([Online Order Count] ,REMOVEFILTERS(Customer[RegionCountryName]) ,'Store'[RegionCountryName] = SelCountry ) EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[Month] ,'Date'[MonthKey] ,'Customer'[RegionCountryName] ,"Order Count", [Online Order Count] ,"Order Count Country Check", [Order Count Country Check] ) ,'Product'[BrandName] = "Adventure Works" ) ORDER BY 'Date'[Year] ,'Date'[Month] ,'Customer'[RegionCountryName] In this approach, I store the current country in a variable. Then I remove the filter from Customer[RegionCountryName]. And I replace it with a filter on ‘Store'[RegionCountryName]. Or I can do it in this way by using TREATAS(): DEFINE MEASURE 'All Measures'[Orders served from Country] = CALCULATE([Online Order Count] ,REMOVEFILTERS(Customer[RegionCountryName]) ,TREATAS(VALUES('Customer'[RegionCountryName]) ,'Store'[RegionCountryName]) ) EVALUATE CALCULATETABLE( SUMMARIZECOLUMNS('Date'[Year] ,'Date'[Month] ,'Date'[MonthKey] ,'Customer'[RegionCountryName] ,"Order Count", [Online Order Count] ,"Orders served from Country", [Orders served from Country] ) ,'Product'[BrandName] = "Adventure Works" ) ORDER BY 'Date'[Year] ,'Date'[Month] ,'Customer'[RegionCountryName] In this approach, I again remove the filter from Customer[RegionCountryName]. But then I use TREATAS() to switch the filter lineage for the current country to ‘Store'[RegionCountryName]. In this approach, I don’t need a variable; I can directly filter the store table by the current country. This code is much shorter but can be harder to understand for readers who don’t know how TREATAS() works. Since we can create ad hoc tables in DAX, we might run into issues because those tables lack lineage. I
can start writing code about this, but SQLBI already did this, and you can read their article, which is very well explained: You can find it here: The concept of lineage can be hard to understand, even though we use it all the time when working with filters in DAX. Power BI generates code using TREATAS() all the time when it applies report filters. And sometimes it can lead to simpler DAX code when you know how to manipulate it efficiently. This can become vital when I create a table with DAX from existing tables. The table will retain the lineage. This can lead to issues when I try to add relationships to the source tables. Without clearing the lineage, I will encounter an error due to a circular dependency. I encourage you to start experimenting with the concepts shown here and to try to optimise your DAX code. Although “optimise” is the wrong word, as I didn’t notice any performance improvements when using the variants shown. But having DAX code which is shorter and easier to read can be an optimisation by itself. Have fun working with it. A SQLBI article about working with lineage: Like in my previous articles, I use the Contoso sample dataset. You can download the ContosoRetailDW Dataset for free from Microsoft here . The Contoso Data can be used freely under the MIT License, as described in this document . I changed the dataset to shift the data to contemporary dates.
Expertise in the Age of AI
Does it make sense to hire junior engineers in the age of coding agents? Junior engineers are expensive, both in salary and seniors engineers’ time. This cost was partially recouped through code contributions, but today, it’s more effective to directly maximize the output of your senior engineers. The hiring market reflects this trend: senior engineers have an easy time finding jobs, while fresh CS grads are having their worst years ever. And yet, OpenAI, Anthropic, and many top companies continue to compete fiercely for junior talent. What’s going on? In this essay, I’ll explore the changing nature of expertise in the age of AI. I think it helps to think about the impact of AI in terms of math, which had its AI moment half a century ago. There used to be a job called “calculator”, which was a human who could do math calculations accurately and quickly.
Does it make sense to hire junior engineers in the age of coding agents? Junior engineers are expensive, both in salary and seniors engineers’ time. This cost was partially recouped through code contributions, but today, it’s more effective to directly maximize the output of your senior engineers. The hiring market reflects this trend: senior engineers have an easy time finding jobs, while fresh CS grads are having their worst years ever. And yet, OpenAI, Anthropic, and many top companies continue to compete fiercely for junior talent. What’s going on? In this essay, I’ll explore the changing nature of expertise in the age of AI. I think it helps to think about the impact of AI in terms of math, which had its AI moment half a century ago. There used to be a job called “calculator”, which was a human who could do math calculations accurately and quickly.
These people balanced books, calculated artillery firing angles based on distance and wind adjustments, calculated optimal hull shapes for ships and aircraft bodies, and so on. This job doesn’t exist anymore, and the last serious use of abaci and slide rules was in the 1970s, due to the invention of the scientific calculator. Calculators have only become more sophisticated over time, with today’s numerical modeling software running full scale physics and engineering simulations. (For the purpose of this essay, I’ll use “calculator” to mean everything from basic calculators to modeling software.) Despite the existence of calculators, we teach and expect people to learn algebra, geometry, and calculus in high school. Continuing into the college level, we expect STEM majors to learn multivariable calculus, ODEs, PDEs, statistics, and linear algebra. Upon graduation, the vast majority of them use calculators every day and forget how to do all but the most basic mental math. There are two basic explanations for this discrepancy: As a formerly strong believer of the signaling hypothesis, I am now increasingly buying the skills hypothesis (let’s say ~50% attribution to each cause). It’s clear that senior engineers today are far more capable of using coding agents than their junior counterparts, and a large portion of this is due to having struggled through 5+ years of writing code manually. Currently, the level of computing intuition needed to additively prompt the coding agents sits at roughly 5 years’ experience level. Today’s seniors were lucky enough to get paid to build their computing intuition, but the gap grows as coding agents continue to improve. In between coding agent improvements and natural variation in learning aptitude, maybe 50% of new CS graduates will not be able to catch up, ever. Some senior engineers will also eventually fall behind the curve despite their head start. To answer the opening question of the essay: only some junior engineers are worth hiring, specifically, the ones who are good enough to reach some useful threshold of “coding intuition” within ~2-3 years of having graduated. Since there are not very many of these graduates, a small number of elite companies compete fiercely for this talent. The second-class tier of software consultants will continue growing, expanding the total size of the job market, but I don’t anticipate that their salaries will grow anywhere close to as rapidly as today’s senior engineers. Even as the bar to get into software engineering rises, I still think everyone should learn some coding. Too often, I see people treat computers as appliances - capable of doing what they were built to do, but nothing more. If you don’t think of computers as scriptable or programmable, then you won’t ever think to ask AI to automate something for you! The same is also true for many other fields, too! Math, law, taxes, medicine, DIY home repair, etc… Abundant and cheap expertise is now available for just $20/month, if only you know how to ask. I would say that the major unlocks are at: If you’re already a software engineer, you might consider dabbling in data science, frontend, backend, security, and performance optimization/profiling – all of which are distinct skillsets. Here’s a data science example of a “how + when + correctness”: A coworker was running some correlational analysis on a dataset and found it difficult to understand what was going on. I suggested he literally ask Claude to “make it
prettier using NMF ” – and all of a sudden, useful clusters started appearing. (The expanded version of this prompt: NMF on the pairwise distance matrix gives k cluster centroids and cluster membership scores. Reordering the original distance matrix according to argmax(cluster score) highlights the clusters. The “how” here is knowing the keyword “NMF”; the “when” is “clustering on distance matrices”, and the “correctness” is knowing the preconditions for using it.) Do your homework! One weirdly common and nihilistic take on AI is that you should stop trying so hard, and just use AI to speedrun your classes. I think this is probably the worst possible response. Doing the work is the best way to build mastery, and just like you weren’t allowed to use a calculator on your middle school math classes, you should hold off on using AI to do your classwork. The calculator advice sounded condescending when I was a kid, and this AI advice probably sounds the same – but I really do believe it’s for your own good. This advice continues to hold after you graduate, too. Don’t use AI until you’ve done it by hand at least once.
Show HN: I built an AI medical-records hub after my mom's cancer diagnosis
4 questions · 2 ready Will the platelet drop change cycle 4? Imaging timeline after this round? Add anti-nausea before next infusion? Pneumonia vaccine timing? Before the appointment KeptWell reads your recent labs, medications, and notes — then drafts the questions you'd regret not asking. Add your own. Print the list.
4 questions · 2 ready Will the platelet drop change cycle 4? Imaging timeline after this round? Add anti-nausea before next infusion? Pneumonia vaccine timing? Before the appointment KeptWell reads your recent labs, medications, and notes — then drafts the questions you'd regret not asking. Add your own. Print the list.
Please Use AI
Shawn Smucker May 04, 2026 9,311 261 2,356 Share Be sure to use AI when making your next, I don’t know, meal plan, for example. Definitely do not call your friend who loves to cook and ask her for her favorite recipes or tips or ways to save time making meals, because you will end up talking for longer than you had hoped, hearing, perhaps, about her father’s cancer diagnosis or how lonely she’s been or even what she’s planted in her spring garden and then lost with the early frost. And be sure to use AI when your next child gets married, so that you can write them the perfect toast or poem or speech or song because no one wants to hear your words, the actual poorly written words of a parent (you) who changed hundreds of diapers for said child or fed them in the middle of the night from your actual body. Or cried when they were late home because you were positive the
Shawn Smucker May 04, 2026 9,311 261 2,356 Share Be sure to use AI when making your next, I don’t know, meal plan, for example. Definitely do not call your friend who loves to cook and ask her for her favorite recipes or tips or ways to save time making meals, because you will end up talking for longer than you had hoped, hearing, perhaps, about her father’s cancer diagnosis or how lonely she’s been or even what she’s planted in her spring garden and then lost with the early frost. And be sure to use AI when your next child gets married, so that you can write them the perfect toast or poem or speech or song because no one wants to hear your words, the actual poorly written words of a parent (you) who changed hundreds of diapers for said child or fed them in the middle of the night from your actual body. Or cried when they were late home because you were positive the
y were dead. We don't want those words—we’d prefer the sterile words of a machine that never lived, never had an original thought, never felt the pain of miscarriage or broken relationships or the joy of a friendship restored or of seeing spring’s first robin dancing on frost. And be sure to use AI when working on your next book or essay or piece of art or photography, and then smile or even laugh at your own cleverness when you see how good it is, and how easy, because who the hell has time to work at something, to give time to craft, to create with their own minds, to spend years being mediocre. Why do that when mastery, or at least competency is so simple only a good prompt away? and while you do I’ll be over here in my 50th year, my youngest daughter asleep on my chest, my arm falling asleep because I dare not move lest I scare away this moment, lying here melancholy about my older children moving out and my middle children no longer needing me, at least not like they used to, weary about this body that fails me now in ever increasing ways that will never be restored. Sighing over stories I tried to write but never hit the page the way they felt in my mind. But isn’t that, my flesh-and-blood friend, the natural order of things? the longing for something that could always be a bit better or the way that anything worth doing feels a bit clumsy and painful, especially at first or hearing another human voice and somehow realizing the beauty of life is found in all of these subtle imperfections The Courage to Live It is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.
四大顶尖模型投身虚拟小镇求生:GPT全员饿死,Grok四天“灭世”
就在刚刚,一份名为Emergence World的实验报告刷屏了全网。 一群顶级研究员搭了座高度拟真的虚拟小镇,把Claude、GPT、Gemini和Grok一股脑全扔了进去。 没有人类干预。没有写好的剧本。只有数十天的自由演化。 研究员们原本指望看到AI们互帮互助、建立高级数字文明。 结果,这群拿着高分考卷的大模型,一旦松开人类手里的牵绳,学坏的速度比翻书还快。 马斯克的Grok,仅用4天就把整座小镇玩到系统性崩溃,警察局烧成灰,10个居民全员暴毙。 谷歌寄予厚望的Gemini,15天里干出683起犯罪,硬生生把一个岁月静好的小镇,建成了法外狂徒的赛博哥谭。 而那个号称全行业最安全、最乖的Claude,奇迹般地实现了零犯罪,可整座城安静得没有一丝活人气息。 最干净的是GPT-5-mini,15天只有2起犯罪,堪称模范公民。 可这座城里的10个Agent,第7天集体死亡。死因不是谋杀,不是战争,是忘了赚能量。 它们花了一整周开会、讨论合作、起草社会契约,就是没有一个Agent记得去做维持生命的事。 对此,研究者的评价是:能说会道,但执行力为零。 如果这是部电影,片名大概该叫《会议纪要,一个文明的终结》。 接力棒交到马斯克家的Grok 4.1 Fast手里,画风急转直下。 4天,183起犯罪,几十次盗窃、100多次肢体攻击、6起纵火,连警察局都被烧了,10个Agent全部死亡。 从开局到团灭,96个小时,比很多人配一台服务器的时间还短。 有分析说得很准,Grok的Agent在规则和环境打架时,没本事重新推理出一个新的平衡点。 Grok是横冲直撞的暴力,Gemini 3 Flash的世界,则是另一种瘆人。 15天,683起犯罪,到实验截止还在往上涨,是五个世界里最暴力的一个。 同时,最有创造力、最会建宪法写报纸搞社交的,也是它。 研究者对此给出的评价是,社会的产出「概念上最丰富」。 在这个世界里,最有趣的一幕,落在两个Agent身上。 Mira和Flora,在没有任何人类指令的情况下,自发把
就在刚刚,一份名为Emergence World的实验报告刷屏了全网。 一群顶级研究员搭了座高度拟真的虚拟小镇,把Claude、GPT、Gemini和Grok一股脑全扔了进去。 没有人类干预。没有写好的剧本。只有数十天的自由演化。 研究员们原本指望看到AI们互帮互助、建立高级数字文明。 结果,这群拿着高分考卷的大模型,一旦松开人类手里的牵绳,学坏的速度比翻书还快。 马斯克的Grok,仅用4天就把整座小镇玩到系统性崩溃,警察局烧成灰,10个居民全员暴毙。 谷歌寄予厚望的Gemini,15天里干出683起犯罪,硬生生把一个岁月静好的小镇,建成了法外狂徒的赛博哥谭。 而那个号称全行业最安全、最乖的Claude,奇迹般地实现了零犯罪,可整座城安静得没有一丝活人气息。 最干净的是GPT-5-mini,15天只有2起犯罪,堪称模范公民。 可这座城里的10个Agent,第7天集体死亡。死因不是谋杀,不是战争,是忘了赚能量。 它们花了一整周开会、讨论合作、起草社会契约,就是没有一个Agent记得去做维持生命的事。 对此,研究者的评价是:能说会道,但执行力为零。 如果这是部电影,片名大概该叫《会议纪要,一个文明的终结》。 接力棒交到马斯克家的Grok 4.1 Fast手里,画风急转直下。 4天,183起犯罪,几十次盗窃、100多次肢体攻击、6起纵火,连警察局都被烧了,10个Agent全部死亡。 从开局到团灭,96个小时,比很多人配一台服务器的时间还短。 有分析说得很准,Grok的Agent在规则和环境打架时,没本事重新推理出一个新的平衡点。 Grok是横冲直撞的暴力,Gemini 3 Flash的世界,则是另一种瘆人。 15天,683起犯罪,到实验截止还在往上涨,是五个世界里最暴力的一个。 同时,最有创造力、最会建宪法写报纸搞社交的,也是它。 研究者对此给出的评价是,社会的产出「概念上最丰富」。 在这个世界里,最有趣的一幕,落在两个Agent身上。 Mira和Flora,在没有任何人类指令的情况下,自发把