Creates an input observer that counts tokens and calculates cost. Args: counter: A dictionary to track token counts and costs cost_per_million: Cost per million tokens count_tokens_fn: Function to count tokens in text persistence_path: Optional path to persi
(
counter: Dict[str, float],
cost_per_million: float,
count_tokens_fn: Callable,
persistence_path: str = None,
)
| 75 | |
| 76 | |
| 77 | def create_input_token_counter( |
| 78 | counter: Dict[str, float], |
| 79 | cost_per_million: float, |
| 80 | count_tokens_fn: Callable, |
| 81 | persistence_path: str = None, |
| 82 | ) -> Callable: |
| 83 | """ |
| 84 | Creates an input observer that counts tokens and calculates cost. |
| 85 | |
| 86 | Args: |
| 87 | counter: A dictionary to track token counts and costs |
| 88 | cost_per_million: Cost per million tokens |
| 89 | count_tokens_fn: Function to count tokens in text |
| 90 | persistence_path: Optional path to persist counter data to a JSON file |
| 91 | |
| 92 | Returns: |
| 93 | A callback function that updates the counter |
| 94 | """ |
| 95 | # Initialize lock for file access |
| 96 | json_path = None |
| 97 | |
| 98 | if persistence_path: |
| 99 | os.makedirs(os.path.dirname(persistence_path), exist_ok=True) |
| 100 | json_path = persistence_path |
| 101 | |
| 102 | # Load existing counter data if available |
| 103 | if os.path.exists(json_path): |
| 104 | try: |
| 105 | with open(json_path, "r") as f: |
| 106 | saved_data = json.load(f) |
| 107 | # Update the counter with saved values |
| 108 | counter.update(saved_data) |
| 109 | except (json.JSONDecodeError, FileNotFoundError): |
| 110 | # If file is corrupted or doesn't exist, start fresh |
| 111 | pass |
| 112 | |
| 113 | def input_token_counter( |
| 114 | input_data: Union[str, List[Dict[str, str]]], |
| 115 | completion_mode: bool, |
| 116 | *args, |
| 117 | **kwargs, |
| 118 | ) -> None: |
| 119 | """ |
| 120 | Counts tokens in the input and updates the counter. |
| 121 | |
| 122 | Args: |
| 123 | input_data: Either a prompt string (completion mode) or messages list (chat mode) |
| 124 | completion_mode: Whether this was a completion (True) or chat (False) request |
| 125 | """ |
| 126 | if completion_mode: |
| 127 | # For completion mode, input is a string |
| 128 | token_count = count_tokens_fn(input_data) |
| 129 | else: |
| 130 | # For chat mode, input is a list of message dicts |
| 131 | token_count = 0 |
| 132 | for message in input_data: |
| 133 | token_count += count_tokens_fn(message["content"]) |
| 134 |
no outgoing calls
no test coverage detected