Context length

#2
by galigator - opened

Thanks for this awesome model.

It works fine with vLLM - I am running it with two A100s at about 33 tokens per second.

The only downside is that when reaching 32k tokens, the model starts outputting random tokens, while it should be fine up to 128k tokens.
Do you have any idea why this behavior occurs?

Neural Magic org

Do you have an example which reproduces this behavior so we can replicate it on our end as well?

Here how I run vllm :
vllm serve neuralmagic/Meta-Llama-3.1-70B-Instruct-quantized.w4a16 --tensor-parallel-size 2 --max-model-len 131072

Here is my test program :
$ cat test_assistant.py

import requests, time
import json, os, sys
from typing import List, Dict

class ChatClient:
    def __init__(self, base_url: str, token: str, model: str):
        """
        Initialise le client de chat.
        
        Args:
            base_url: URL du service (ex: 'http://localhost:8000')
            token: Token d'authentification
            model: Nom du modèle à utiliser
        """
        self.base_url = base_url.rstrip('/')
        self.headers = {
            'accept': 'application/json',
            'Content-Type': 'application/json',
            'Authorization': f'Bearer {token}'
        }
        self.model = model
        self.messages = [
            {
                "content": "You are a helpful assistant",
                "role": "system"
            }
        ]
        self.total_tokens = 0
        self.context_len = 24*1024 - 80
        # Statistiques de performance
        self.total_time = 0
        self.total_completion_tokens = 0

    def add_message(self, content: str, role: str = "user") -> None:
        """Ajoute un message à l'historique."""
        self.messages.append({
            "content": content,
            "role": role
        })

    def call_api(self) -> Dict:
        """Fait l'appel à l'API et retourne la réponse."""
        max_tokens = self.context_len - self.total_tokens
        print("Je peux encore produire : ", max_tokens, " tokens")
        payload = {
            "messages": self.messages,
            "model": self.model,
            "max_tokens": max_tokens,
            "n": 1,
            "stream": False,
            "temperature": 0.9,
            "priority": 0
        }

        start_time = time.time()
        response = requests.post(
            f'{self.base_url}/v1/chat/completions',
            headers=self.headers,
            json=payload
        )
        elapsed_time = time.time() - start_time
        
        if response.status_code != 200:
            raise Exception(f"Erreur API: {response.status_code} - {response.text}")
            
        response_data = response.json()
        
        # Mettre à jour les statistiques de performance
        completion_tokens = response_data.get('usage', {}).get('completion_tokens', 0)
        self.total_time += elapsed_time
        self.total_completion_tokens += completion_tokens
        
        # Ajouter les informations de performance à la réponse
        response_data['performance'] = {
            'elapsed_time': elapsed_time,
            'tokens_per_second': completion_tokens / elapsed_time if elapsed_time > 0 else 0,
            'average_tokens_per_second': self.total_completion_tokens / self.total_time if self.total_time > 0 else 0
        }
            
        return response_data

    def display_token_info(self, response: Dict) -> None:
        """Affiche les informations sur l'utilisation des tokens."""
        usage = response.get('usage', {})
        performance = response.get('performance', {})
        prompt_tokens = usage.get('prompt_tokens', 0)
        completion_tokens = usage.get('completion_tokens', 0)
        total_tokens = usage.get('total_tokens', 0)
        
        self.total_tokens += total_tokens
        
        print("\n--- Utilisation des tokens pour cet échange ---")
        print(f"Tokens prompt: {prompt_tokens}")
        print(f"Tokens réponse: {completion_tokens}")
        print(f"Total pour cet échange: {total_tokens}")
        print(f"Total cumulé de la conversation: {self.total_tokens}")
        print("\n--- Performance ---")
        print(f"Temps de génération: {performance.get('elapsed_time', 0):.2f} secondes")
        print(f"Débit instantané: {performance.get('tokens_per_second', 0):.2f} tokens/seconde")
        print(f"Débit moyen: {performance.get('average_tokens_per_second', 0):.2f} tokens/seconde")
        print("-------------------------------------------")


    def process_input(self, user_input: str) -> bool:
        """
        Traite une entrée utilisateur et retourne False si on doit quitter.
        
        Args:
            user_input: L'entrée utilisateur à traiter
            
        Returns:
            bool: False si on doit quitter, True sinon
        """
        if user_input.lower() == 'quit':
            print("Au revoir!")
            return False
            
        # Ajouter le message utilisateur et faire l'appel
        self.add_message(user_input)
        
        try:
            response = self.call_api()
            
            # Extraire et afficher la réponse
            assistant_message = response['choices'][0]['message']['content']
            print(f"\nAssistant: {assistant_message}")
            
            # Ajouter la réponse à l'historique
            self.add_message(assistant_message, "assistant")

            # Afficher les informations sur les tokens
            self.display_token_info(response)
            
        except Exception as e:
            print(f"\nErreur: {str(e)}")
            
        return True


    def chat_loop(self, input_file: str = None):
        """
        Démarre une boucle de chat interactive ou lit depuis un fichier.
        
        Args:
            input_file: Chemin vers le fichier d'entrée (optionnel)
        """
        if input_file:
            try:
                with open(input_file, 'r', encoding='utf-8') as f:
                    for line in f:
                        line = line.strip()
                        if line:  # Ignorer les lignes vides
                            print(f"\nVous: {line}")
                            if not self.process_input(line):
                                break
            except FileNotFoundError:
                print(f"Erreur: Le fichier '{input_file}' n'existe pas.")
                return
            except Exception as e:
                print(f"Erreur lors de la lecture du fichier: {str(e)}")
                return
        else:
            print("Bienvenue! Tapez 'quit' pour quitter.")
            while True:
                user_input = input("\nVous: ").strip()
                if not self.process_input(user_input):
                    break

def main():
    # Obtenir les variables d'environnement ou utiliser des valeurs par défaut
    base_url = os.getenv('MY_IP_PORT', 'http://localhost:8000')
    if not base_url.startswith('http'):
        base_url = f'http://{base_url}'
    
    token = os.getenv('MY_TOKEN', 'mytoken')
    model = os.getenv('MY_MODEL', 'neuralmagic/Llama-3.1-Nemotron-70B-Instruct-HF-FP8-dynamic')

    # Vérifier si un fichier est fourni en argument
    input_file = sys.argv[1] if len(sys.argv) > 1 else None

    # Créer et démarrer le client
    client = ChatClient(base_url, token, model)
    client.chat_loop(input_file)

if __name__ == "__main__":
    main()
``

here how I run my test program : 
$ python test_assistant.py interactions.txt

here the content of the file interactions.txt require to automate testing (each line will count as was input from the user)
$ cat interactions.txt
Créer un jeu de sudoku en python avec un IHM. N'oublie de permettre à l'utilisateur de générer de nouvelle grille, la fonction de résolution automatique, et les fonctions permettant à l'utilisateur de placer et retirer ces propres chiffres.
Ajoute une base de donnée pour stocker les parties, les temps de résolutions par utilisateur, la difficulté. Puis ajoute des fonctions de visualisation de statistique à partir de la base de données avec des projections sur les performances futures.
Ajoute une boite de contrôle qui permet à l'utilisateur de changer les couleurs du jeu. Notamment les couleurs utilisé pour marqué les nombres mal placé ou bien placé, la couleurs de visualisation graphiques. Ajoute aussi une fonction pour sauvegarder et reprendre le jeu.
Ajoute 20 grilles par défaut dans la base de données. 5 très faciles, 5 faciles, 5 moyennes, et 5 difficiles.
Ajoute un déploiement Heroku et une intégration Facebook.
Écris la notice utilisateur en html, pour Français et Anglais.
Sur le même modèle que le jeu de sudoku, ajoute un jeu de pendu, avec les même fonctions, intégration, stockage et système de prévision.
Pour plus de performances converti les programmes python en rust.
Neural Magic org

Just to clarify: the example code snippet you shared uses the neuralmagic/Meta-Llama-3.1-70B-Instruct-quantized.w4a16 model, while the issue you mentioned is opened at the neuralmagic/Llama-3.1-Nemotron-70B-Instruct-HF-FP8-dynamic model. Could you please clarify which model is causing problems for you with the 32k context inputs?

Forgive me, vllm use "neuralmagic/Llama-3.1-Nemotron-70B-Instruct-HF-FP8-dynamic" like in the test script. I miss copy the wrong test from another test set.
run command is :

vllm serve neuralmagic/Llama-3.1-Nemotron-70B-Instruct-HF-FP8-dynamic --tensor-parallel-size 2 --max-model-len 131072

even if you have down a really good job on Meta-Llama-3.1-70B-Instruct-quantized.w4a16 too.
The hype is on Nemoton.

Sign up or log in to comment