Token limits refer to the maximum number of tokens that a language model can process in a single input prompt or output generation. A token limit affects how much text you can send to a model in one go. A language model provider should provide information about the token limits for each model that is associated with your account and API key. When running a big job in EDSL, you may encounter token limits, which can be managed by adjusting the token limits for a model.
RPM stands for Requests Per Minute, which measures the number of API requests that a user can make to a language model within a minute. This is a metric for managing the load and traffic that a model can handle.
TPM stands for Tokens Per Minute, which is a metric for tracking the volume of tokens processed by a language model within a minute. This metric typically tracks usage for billing purposes.
We can reset the default RPM and TPM and then check the new values:
model = Model()model.rpm=10model.tpm=10[model.rpm, model.tpm]
This will show the following information:
[10, 10]
Here we change it again:
model = Model()model.rpm=100model.tpm=1000[model.rpm, model.tpm]
Output:
[100, 1000]
Please note that the token limits are subject to the constraints of the model and the API key associated with the model. Let us know if you have any questions or need further assistance with token limits.
Each question type (other than free_text) automatically includes a comment field that gives the answering model a place to put additional information about its response to a question. This serves as an outlet for a chatty model to return context about an answer without violating formatting instructions (e.g., a model may want to provide an explanation for a mutiple choice response but the answer to the question must only be one of the answer options). Question comments can also be useful when used with survey “memory” rules, giving a model an opportunity to simulate a “chain of thought” across multiple survey questions. (By default, questions are administered asynchronously; a model does not have context of other questions and answers in a survey unless memory rules are applied.) Comments can also provide insight into non-responsive (None) answers: a model may use the comments field to describe a point of confusion about a question.Because the question comment field requires additional tokens, it can sometimes be cost-effective to exclude the field from question prompts, especially when the comment is unlikely to be useful. This is done by passing a boolean parameter include_comment = False when constructing a question. For example, here we compare a question with comments left on and turned off:
from edsl import QuestionNumerical, Survey, ScenarioListq1 = QuestionNumerical( question_name = "sum", question_text = "What is the sum of {{ number_1 }} and {{ number_2 }}?")q2 = QuestionNumerical( question_name = "sum_silent", question_text = "What is the sum of {{ number_1 }} and {{ number_2 }}?", include_comment = False)survey = Survey([q1, q2])some_numbers = { "number_1": [0,1,2,3,4], "number_2": [5,4,3,2,1]}s = ScenarioList.from_nested_dict(some_numbers)results = survey.by(s).run()
We can check the responses and confirm that the comment field for the sum_silent question is None:
Question instructions can be modified to prompt a model to use codes (integers) in lieu of text responses for answer options, reducing generated tokens.This is done by passing a boolean parameter use_code = True to a Question when it is constructed. For example:
from edsl import QuestionMultipleChoiceq = QuestionMultipleChoice( question_name = "income_pref_coded", question_text = "Which of the following is more important to you: ", question_options = ["Financial stability", "Moving up the income ladder"], use_code = True)
We can inspect the difference in the question prompt that is created by creating an identical question without the parameter and comparing the job prompts. Here we also pass the parameter include_comment = False:
from edsl import QuestionMultipleChoice, Survey, Agent, Modelq1 = QuestionMultipleChoice( question_name = "income_pref", question_text = "Which of the following is more important to you: ", question_options = ["Financial stability", "Moving up the income ladder"])q2 = QuestionMultipleChoice( question_name = "income_pref_coded", question_text = "Which of the following is more important to you: ", question_options = ["Financial stability", "Moving up the income ladder"], use_code = True, include_comment = False)survey = Survey([q1, q2])# Construct a job with the survey and the default modeljob = survey.by(Model())# Inspect the question promptsjob.prompts().select("question_index", "user_prompt")
Output:
question_index
user_prompt
income_pref
Which of the following is more important to you: Financial stability Moving up the income ladder Only 1 option may be selected. Respond only with a string corresponding to one of the options. After the answer, you can put a comment explaining why you chose that option on the next line.
income_pref_coded
Which of the following is more important to you: 0: Financial stability 1: Moving up the income ladder Only 1 option may be selected. Respond only with the code corresponding to one of the options.
The prompts can also be inspected after the survey is run:
Which of the following is more important to you: Financial stability Moving up the income ladder Only 1 option may be selected. Respond only with a string corresponding to one of the options. After the answer, you can put a comment explaining why you chose that option on the next line.
Financial stability provides a secure foundation and peace of mind, allowing for better long-term planning and resilience against unexpected challenges.
Which of the following is more important to you: 0: Financial stability 1: Moving up the income ladder Only 1 option may be selected. Respond only with the code corresponding to one of the options.
If no agents are used with the survey, the base agent instructions are not sent to the model, reducing overall tokens. (This is a change from prior versions of EDSL.)
We can monitor tokens by calculating next token probabilities. This is done by setting model logprobs = True and then accessing the raw_model_response information in the results that are generated. For example:
from edsl import QuestionMultipleChoice, Agent, Modelm = Model("gpt-4o", temperature = 1, logprobs = True)a = Agent(traits = {"persona":"financial advisor"})q = QuestionMultipleChoice( question_name = "income_pref_coded", question_text = "Which of the following is more important to you: ", question_options = ["Financial stability", "Moving up the income ladder"], use_code = True, include_comment = False)results = q.by(a).by(m).run()example = results.select("raw_model_response.income_pref_coded_raw_model_response").to_list()[0]exampleOutput:{'id': 'chatcmpl-AcgR7Wy6MMDqoorytBlzS2lzpwQAA','choices': [{'finish_reason': 'stop','index': 0,'logprobs': {'content': [{'token': '0', 'bytes': [48], 'logprob': -0.00019960667, 'top_logprobs': [{'token': '0', 'bytes': [48], 'logprob': -0.00019960667}, {'token': '1', 'bytes': [49], 'logprob': -9.000199}, {'token': 'As', 'bytes': [65, 115], 'logprob': -10.875199}]}], 'refusal': None},'message': {'content': '0', 'refusal': None, 'role': 'assistant', 'audio': None, 'function_call': None, 'tool_calls': None}}],'created': 1733782953,'model': 'gpt-4o-2024-08-06','object': 'chat.completion','service_tier': None,'system_fingerprint': 'fp_9d50cd990b','usage': {'completion_tokens': 1,'prompt_tokens': 82,'total_tokens': 83,'completion_tokens_details': {'accepted_prediction_tokens': 0,'audio_tokens': 0,'reasoning_tokens': 0,'rejected_prediction_tokens': 0},'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}}
We can use the information to calculate next token probabilities:
import math# Specifying the codes for the answer options and non-responses:options = {'0': "Financial stability", '1':"Moving up the income ladder"}for token_info in next_token_probs: option = options.get(token_info['token'], None) if option: p = math.exp(token_info['logprob']) print(f"Probability of selecting '{option}' was {p:.3f}")
Output:
Probability of selecting 'Financial stability' was 0.992Probability of selecting 'Moving up the income ladder' was 0.008