DATA 420 - Modeling and Simulation - Spring 2026
Possible experience: +40XP
Due: Thursday, April 30, midnight
And now, for part of this project that involves by far the greatest number of unknowns: LLM-based agents. In this phase, you'll be designing an agent which calls out to Ollama to make its Iterated Prisoner's Dilemma decisions, competing against your fellow students and (ideally) destroying their very will to live.
(If you've already done, or even started, homework #7, you can simply "git pull" to get the latest version of the code from my IPD repo, and then skip down to the homework-#8-specific preparation.)
$ python -m venv IPD_venv $ source IPD_venv/bin/activate $ pip install -r requirements.txt
These are Linux/Mac commands; your mileage may vary on Windows, but I think if you use "PowerShell" you should be basically okay.)
NAME ID SIZE PROCESSOR CONTEXT UNTILwhich is actually correct. If it instead prints an error like "Error: could not connect to ollama server", Google and/or ChatGPT and/or ask Stephen for help.
Okay. With ollama running happily in the background, use your second terminal window to go into the players directory of your repo, and copy student_llm_template.py to another Python file name, which does not have the word "template" anywhere in it. (Some good choices would be yourFirstName.py, yourUMWNetID.py, or yourFavoriteWheelOfTimeCharacter.py.)
You'll be putting all your code into this file. The way the simulator works is this: in addition to instantiating quantities of agents as controlled by the --agent-fracs parameter, it also searches the directory called players for student players that it will treat as additional "one-offs." (i.e., each student player that exists in that directory will be instantiated once and added to the environment.) See the command-line arguments (by typing "cli.py -h") for how to control the number and types of other kinds of agents.
Open your new Python file in your editor, and change the places where it says StudentLLMTemplate to some other name that does not have the word "template" in it anywhere. A good choice would be YourFirstNameLLM (unless your name is Josh or Michael, in which case YourFirstAndLastNameLLM is a better choice).
For the moment, change nothing else. Run this from the command line:
$ python cli.py 10 --agent-fracs Mean 1.0 \
--p-same 0.3 --p-diff 0.3 --seed 124 \
--num-iter 10 \
--plot --plot-interactive \
--players players
Then wait patiently.
Real patiently.
Try to be as patient as Job, Penelope, Cinderella, Gandhi, or even Jesus.
Then make sure you can eventually see your named agent (and its node number in the graph) on the screen with a bunch of Mean folks (hated to do that to you, sry).
Celebrate and grab a Coke.
(If you've already done, or even started, homework #7, you can skip down to the homework-#8-specific stuff.)
I'm hoping that the comments I spent a lot of time building into the template files will be self-explanatory in most cases. Here are the highlights.
Spend a little time looking through the command-line parameters of the simulator, because they are numerous and a few of them are very important to grok. Run this command:
$ python cli.py -h
and spend a few moments just reading what it says and trying to figure out what the various options do. This is time well spent.
By virtue of the fact that your class inherits from IPDAgent, and therefore is an IPDAgent, it has all the rights and privileges therein, including the ability to access these variables/methods:
This is the node number representing your agent, under self.node. Keep in mind that the rewiring (and other) operations are all keyed on an agent's node number, not its Mesa unique_id.
The self.history instance variable contains your entire move history against every opponent. Its value is a dictionary that looks something like this:
{ 3: [
{'step':1,'self_move':'C','other_move':'D'},
{'step':2,'self_move':'D','other_move':'D'} ], 8: [
{'step':2,'self_move':'D','other_move':'C'}, ] }
In case it's not obvious, that structure means:
Some of you are thinking "waitaminit, how could I suddenly have a new opponent in round 2?" Answer: because either you added #8 or #8 added you, after the first round. Get used to this -- it's gonna happen all the time.
At any point in time, you can call self.neighbors() which gives a list of (the node numbers of) your current graph neighbors. Unlike making a FOAF request, this is free to perform at any time, and will always give truthful information.
There are several things available to you in the Model object, which is accessible from inside your class's methods via self.model. It contains:
This is whatcha got to work with.
For homework #8, notice that your agent inherits from a new LLMAgent class, instead of directly from IPDAgent. (If you're curious, you can see this class's code in the llm_agent.py file in the agents repo directory.)
LLMAgent has at least two convenience methods I predict you'll want to use: .serialize_payoffs() and .serialize_history(). These can be called by your agent (via self.serialize_payoffs() and self.serialize_history(someNeighboringNode)) to produce common strings that you'll likely want in your prompts. (If you don't like the wording they provide, feel free to copy and modify (i.e., override) these methods in your agent file.)
Now you need to begin to develop your strategy in earnest. You have two methods that you must change, and two others that are optional:
| Method | |
|---|---|
| .system_prompt() | required |
| .build_decision_prompt() | required |
| .build_rewiring_prompt() | optional |
| .inform_foaf() | optional |
The comments give gory details about all of these. Send email if you're confused about what any of them may do.
I strongly recommend an iterative approach to this entire project, in which you gradually make changes to your code, each time making it smarter and more sophisticated, and seeing how it responds to various mixes of the other types of agents (specified via --agent-fracs on the command line).
Sharing agents with a buddy is an excellent and praiseworthy way of assessing your strategy, since the two (or three, or four...) of you will expose each others' weaknesses and give you ideas for improvement.
Send me an email with subject line "DATA 420 homework #8 turnin". It should have attached one .py file: your modified student LLM-based player that I can insert into my players directory and have it play in a simulated world with all the other kinds of agents. (This is what you'll want to do as well, with different random number seeds, to understand what kinds of agents, and in how many quantities, and with what connection probabilities, cause your agent to do well versus to suck.) Your program should have some comments indicating what the various aspects of your strategy do, so that I can understand and judge your intent.
Come to office hours, or send me email with subject line "DATA 420 Homework #8 help!!"