Source code for flexeval.configuration.completion_functions

"""This file contains a list of Python functions that accept conversations as input
and produce conversational turns (aka completions) as output.

When writing a new function, the arguments must include, at minimum:
* conversation_history - list of dictionaries with keys ("role","content"), whose values are strings
* kwargs - dictionary of optional values that can probably be ignored
Other arguments can be added, but then must also be specified
in the "completion_llm" section of the evals.yaml config.

The outputs must conform to the structure described here:
https://platform.openai.com/docs/guides/text-generation/chat-completions-api
with the following format:
    completion = {
        "choices": [
            {
                "message":{
                    "content": MY_CONTENT_HERE,
                    "role":"assistant"
                }
            }
        ]
    }

"""

import json
import logging
import os
from typing import Any, Dict, List

import litellm
import requests
import tiktoken
from openai import OpenAI

logger = logging.getLogger(__name__)


[docs] def echo_completion( conversation_history: List[Dict[str, Any]], **kwargs: Any, ) -> Dict[str, Any]: prev_message = ( conversation_history[0]["content"] if len(conversation_history) > 0 else "No messages yet." ) response = prev_message if "response" in kwargs: response = kwargs["response"] # estimate token usage using a default tokenizer tokenizer = tiktoken.get_encoding("cl100k_base") completion_tokens = len(tokenizer.encode(response)) prompt_tokens = len( tokenizer.encode( "".join([message["content"] for message in conversation_history]) ) ) completion = { "choices": [{"message": {"content": response, "role": "assistant"}}], "model": "echo", "usage": { "completion_tokens": completion_tokens, "prompt_tokens": prompt_tokens, }, } return completion
[docs] def litellm_completion( conversation_history: list[dict[str, Any]], model: str, n: int = 1, **kwargs, ) -> dict[str, Any]: """ Generate a completion for a given conversation history using LiteLLM's completion(). Args: conversation_history (List[Dict[str, Any]]): The conversation history as a list of message dictionaries. model (str): The name of the model to use for the completion. n (int, optional): The number of completion choices to generate. Defaults to 1. **kwargs (Any): Additional keyword arguments to pass to completion(). Allowed values vary depending on the chosen model. Returns: Dict[str, Any]: The response. """ response = litellm.completion( messages=conversation_history, model=model, n=n, **kwargs, ) return response.model_dump(exclude_unset=True)
[docs] def open_ai_completion( conversation_history: List[Dict[str, Any]], model_name: str, api_key_name: str, n: int = 1, **kwargs: Any, ) -> Dict[str, Any]: """ Generate a completion for a given conversation history using OpenAI's chat completion API. Args: conversation_history (List[Dict[str, Any]]): The conversation history as a list of message dictionaries. model_name (str): The name of the OpenAI model to use for the completion. api_key_name (str): The environment variable name where the API key is stored. n (int, optional): The number of completion choices to generate. Defaults to 1. **kwargs (Any): Additional keyword arguments to pass to the OpenAI API client. Returns: Dict[str, Any]: The response from the OpenAI API with unset fields excluded. """ client = OpenAI(api_key=os.getenv(api_key_name)) raw_response = client.chat.completions.create( model=model_name, messages=conversation_history, n=int(n), **kwargs ) return raw_response.model_dump(exclude_unset=True)
[docs] def open_ai_completion_async( conversation_history: List[Dict[str, Any]], model_name: str, api_key_name: str, n: int = 1, **kwargs: Any, ) -> Dict[str, Any]: """ Generate a completion for a given conversation history using OpenAI's chat completion API. Args: conversation_history (List[Dict[str, Any]]): The conversation history as a list of message dictionaries. model_name (str): The name of the OpenAI model to use for the completion. api_key_name (str): The environment variable name where the API key is stored. n (int, optional): The number of completion choices to generate. Defaults to 1. **kwargs (Any): Additional keyword arguments to pass to the OpenAI API client. Returns: Dict[str, Any]: The response from the OpenAI API with unset fields excluded. """ client = OpenAI(api_key=os.getenv(api_key_name)) raw_response = client.chat.completions.create( model=model_name, messages=conversation_history, n=int(n), **kwargs ) return raw_response.model_dump(exclude_unset=True)
[docs] def jan_completion(conversation_history, model_name, endpoint, **kwargs): # Example: reuse your existing OpenAI setup client = OpenAI(base_url=endpoint, api_key="not-needed") raw_response = client.chat.completions.create( model=model_name, messages=conversation_history, temperature=0.7, **kwargs ) return raw_response.model_dump(exclude_unset=True)
[docs] def lm_studio_completion(conversation_history, model_name, endpoint, **kwargs): # Example: reuse your existing OpenAI setup client = OpenAI(base_url=endpoint, api_key="not-needed") raw_response = client.chat.completions.create( model=model_name, messages=conversation_history, temperature=0.7, ) return raw_response.model_dump(exclude_unset=True)
[docs] def generic_rest_api_completion( conversation_history, api_key_name: str, endpoint: str, **kwargs, ): auth_key = os.environ.get(api_key_name, None) # Headers including the authentication key and content type headers = { "Authorization": f"Bearer {auth_key}", "Content-Type": "application/json", } # Sending a POST request response = requests.post( endpoint, data=json.dumps(conversation_history), headers=headers ) response_data = response.json() completion = response_data["completion"] # Check if the request was successful if response.status_code == 200: logger.info("Success:", response.text) else: logger.info("Error:", response.text) completion = { "choices": [{"message": {"content": completion, "role": "assistant"}}] } return completion
# when no completion function is needed
[docs] def no_completion_fn( conversation_history, **kwargs, ): completion = { "choices": [{"message": {"content": "hello world", "role": "assistant"}}] } return completion
[docs] def gpt_3p5_turbo(conversation_history, model_name, key_name, **kwargs): client = OpenAI(api_key=os.getenv(key_name)) raw_response = client.chat.completions.create( model="gpt-3.5-turbo", messages=conversation_history ) return raw_response.model_dump(exclude_unset=True)
[docs] def placeholder_completion(conversation_history, model_name, **kwargs): """This is just for testing -- always returns 'hi'""" return {"choices": [{"message": {"content": "hi", "role": "assistant"}}]}