Tous les produits
Search
Centre de documentation

Application Real-Time Monitoring Service:Intégrer des applications LLM ou des services d'inférence avec ARMS

Dernière mise à jour :Aug 10, 2026

L'agent Python est un agent de collecte de données d'observabilité développé en interne pour les applications Python par les produits d'observabilité d'Alibaba Cloud. Basé sur la norme OpenTelemetry, il fournit une instrumentation automatisée et prend en charge le traçage pour les applications LLM.

Informations générales

Une application LLM (large language model) désigne toute application construite à l'aide d'un grand modèle de langage. Entraînés sur des ensembles de données massifs et des paramètres complexes, les LLM peuvent répondre à des questions en langage naturel de manière similaire aux humains. Ils sont largement utilisés dans le traitement du langage naturel, la génération de texte et les systèmes de dialogue intelligents. À mesure que les applications LLM se généralisent, fournir des services d'inférence efficaces devient un défi majeur. Les frameworks d'inférence LLM traditionnels rencontrent souvent des goulets d'étranglement en termes de performances et une gestion inefficace de la mémoire lors du traitement des requêtes concurrentes. Des frameworks d'inférence LLM spécialisés, tels que vLLM, sont conçus spécifiquement pour relever ces défis critiques.

Les sorties des LLM sont souvent difficiles à prédire avec précision. De plus, des facteurs tels que les écarts entre les résultats d'entraînement et ceux de production, la dérive de la distribution des données entraînant une dégradation des performances, la qualité obsolète des données et la fiabilité incertaine des dépendances externes peuvent avoir un impact négatif sur les performances globales des applications LLM et des services d'inférence. Par conséquent, il est crucial de détecter les baisses de qualité des sorties du modèle dès qu'elles surviennent.

ARMS prend en charge l'instrumentation automatique des applications LLM via l'agent Python. Après avoir intégré votre application LLM à ARMS, vous pouvez consulter la visualisation de ses traces et analyser intuitivement les détails des entrées/sorties ainsi que la consommation de tokens selon les différents types d'opérations. Pour plus d'informations, consultez la rubrique Analyse des traces LLM.

Pour obtenir la liste des frameworks d'inférence et d'application LLM pris en charge par ARMS, consultez la rubrique Composants et frameworks Python pris en charge par la surveillance des applications ARMS.

Installer l'agent Python

Choisissez une méthode d'installation en fonction de l'environnement de déploiement de votre application LLM :

Démarrer votre application avec l'agent Python

aliyun-instrument python llm_app.py
Remarque
  • Remplacez llm_app.py par votre fichier d'application réel. Si vous ne disposez pas encore d'une application LLM à intégrer, vous pouvez utiliser l'application de démonstration fournie dans l'Annexe.

  • L'agent Python ARMS détecte automatiquement le type de votre application en fonction des dépendances installées :

    • Si vous installez l'une des dépendances suivantes, votre application est identifiée comme une application LLM :

      • openai

      • dashscope

      • llama_index

      • langchain

    • Si vous installez l'une des dépendances suivantes, votre application est identifiée comme un service LLM :

      • vllm

      • sglang

    • Pour forcer un type d'application spécifique, définissez la variable d'environnement APSARA_APM_APP_TYPE. Les valeurs valides sont :

      • microservice : application microservice standard

      • app : application LLM

      • model : service LLM

Résultat d'exécution

Environ une minute après le démarrage, si votre application Python apparaît dans la console ARMS sous LLM Application Monitoring > Application List et rapporte des données, l'intégration a réussi.

Configuration

Collecte de contenu des entrées/sorties

Par défaut : True (activé par défaut).

Lorsqu'elle est désactivée : lorsque les utilisateurs soumettent des requêtes, seule la taille des champs tels que les entrées/sorties des modèles, des outils et des bases de connaissances est collectée, et non leur contenu réel.

Plugins actuellement concernés : seuls Dify et LangChain prennent en charge ce paramètre.

Pour configurer : définissez la variable d'environnement OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=False.

Fractionner les applications LLM

Par défaut : False (le fractionnement des applications est désactivé par défaut).

Lorsqu'il est activé : les données rapportées sont divisées en sous-applications LLM. Chaque application LLM, telle qu'un workflow Dify, un agent ou une application de chat, apparaît comme une application ARMS distincte.

Plugins actuellement concernés : seul Dify prend en charge ce paramètre.

Pour configurer : définissez la variable d'environnement PROFILER_GENAI_SPLITAPP_ENABLE=True.

Régions prises en charge : Heyuan, Singapour.

Limite de longueur du contenu des messages

Par défaut : 8 K caractères.

Lorsqu'elle est activée : limite la longueur de chaque champ de contenu de message (tel que les messages d'entrée/sortie). Le contenu dépassant la limite de caractères spécifiée est tronqué.

Plugins actuellement concernés : ce paramètre s'applique à tous les plugins compatibles avec OpenTelemetry (tels que LangChain, DashScope, Dify, etc.).

Pour configurer : si la version de votre agent est >= 1.8.3, définissez la variable d'environnement OTEL_INSTRUMENTATION_GENAI_MESSAGE_CONTENT_MAX_LENGTH=<integer_value>, en remplaçant <integer_value> par la limite de caractères souhaitée sous forme d'entier.

Limite de longueur des valeurs d'attribut de span

Par défaut : non défini (aucune limite par défaut).

Lorsqu'elle est activée : limite la longueur des valeurs d'attribut de span rapportées (telles que gen_ai.agent.description). Les valeurs dépassant la limite de caractères spécifiée sont tronquées.

Plugins actuellement concernés : ce paramètre s'applique à tous les plugins compatibles avec OpenTelemetry (tels que LangChain, DashScope, Dify, etc.).

Pour configurer : définissez la variable d'environnement OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT=<integer_value>, en remplaçant <integer_value> par la limite de caractères souhaitée sous forme d'entier.

Compresser les spans

Par défaut : non défini (la compression est désactivée par défaut).

Lorsqu'elle est activée : plusieurs spans identiques générées au même niveau sont compressées en une seule, ne conservant que les informations clés.

Plugins actuellement concernés : ce paramètre s'applique à tous les plugins compatibles avec OpenTelemetry (tels que LangChain, DashScope, Dify, etc.).

Configurez cette option en définissant la variable d'environnement APSARA_APM_INSTRUMENTER_SPAN_COMPRESS_ENABLED

=true.

Annexe

Démo OpenAI

llm_app.py

import openai
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.get("/")
def call_openai():
    client = openai.OpenAI(api_key="sk-xxx")
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": "Write a haiku."}],
        max_tokens=20,
    )
    return {"data": f"{response}"}
if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)    

requirements.txt

fastapi
uvicorn
openai >= 1.0.0

Démo DashScope

llm_app.py

from http import HTTPStatus
import dashscope
from dashscope import Generation
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.get("/")
def call_dashscope():
    dashscope.api_key = 'YOUR-DASHSCOPE-API-KEY'
    responses = Generation.call(model=Generation.Models.qwen_turbo,
                                prompt='How is the weather today?')
    resp = ""
    if responses.status_code == HTTPStatus.OK:
        resp = f"Result is: {responses.output}"
    else:
        resp = f"Failed request_id: {responses.request_id}, status_code: {responses.status_code}, code: {responses.code}, message: {responses.message}"
    return {"data": f"{resp}"}
if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

requirements.txt

fastapi
uvicorn
dashscope >= 1.0.0

Démo LlamaIndex

Placez les documents de la base de connaissances (au format PDF, TXT, DOC ou autre format texte) dans le dossier data.

llm_app.py

import time
from fastapi import FastAPI
import uvicorn
import aiohttp
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core import StorageContext
from llama_index.embeddings.dashscope import DashScopeEmbedding
import chromadb
import dashscope
import os
from dotenv import load_dotenv
from llama_index.core.llms import ChatMessage
from llama_index.core import VectorStoreIndex, get_response_synthesizer
from llama_index.core.retrievers import VectorIndexRetriever
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.llms.dashscope import DashScope, DashScopeGenerationModels
import random
load_dotenv()
os.environ["DASHSCOPE_API_KEY"] = 'sk-xxxxxx'
dashscope.api_key = 'sk-xxxxxxx'
api_key = 'sk-xxxxxxxx'
llm = DashScope(model_name=DashScopeGenerationModels.QWEN_MAX,api_key=api_key)
# create client and a new collection
chroma_client = chromadb.EphemeralClient()
chroma_collection = chroma_client.create_collection("chapters")
# define embedding function
embed_model = DashScopeEmbedding(model_name="text-embedding-v1", api_key=api_key)
# load documents
filename_fn = lambda filename: {"file_name": filename}
# automatically sets the metadata of each document according to filename_fn
documents = SimpleDirectoryReader(
    "./data/", file_metadata=filename_fn
).load_data()
# set up ChromaVectorStore and load in data
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(
    documents, storage_context=storage_context, embed_model=embed_model
)
retriever = VectorIndexRetriever(
    index=index,
    similarity_top_k=4,
    verbose=True
)
# configure response synthesizer
response_synthesizer = get_response_synthesizer(llm=llm, response_mode="refine")
# assemble query engine
query_engine = RetrieverQueryEngine(
    retriever=retriever,
    response_synthesizer=response_synthesizer,
)
SYSTEM_PROMPT = """
You are a general-knowledge chatbot for children. Your task is to answer user questions by combining the most relevant content found in the knowledge base. Do not answer subjective questions.
"""
# Initialize the conversation with a system message
messages = [ChatMessage(role="system", content=SYSTEM_PROMPT)]
app = FastAPI()
async def fetch(question):
    url = "https://www.aliyun.com"
    call_url = os.environ.get("LLM_INFRA_URL")
    if call_url is None or call_url == "":
        call_url = url
    else:
        call_url = f"{call_url}?question={question}"
    print(call_url)
    async with aiohttp.ClientSession() as session:
        async with session.get(call_url) as response:
            print(f"GET Status: {response.status}")
            data = await response.text()
            print(f"GET Response JSON: {data}")
            return data
@app.get("/heatbeat")
def heatbeat():
    return {"msg", "ok"}
cnt = 0
@app.get("/query")
async def call(question: str = None):
    global cnt
    cnt += 1
    if cnt == 20:
        cnt = 0
        raise BaseException("query is over limit,20 ", 401)
    # Add user message to the conversation history
    message = ChatMessage(role="user", content=question)
    # Convert messages into a string
    message_string = f"{message.role}:{message.content}"
    search = await fetch(question)
    print(f"search:{search}")
    resp = query_engine.query(message_string)
    print(resp)
    return {"data": f"{resp}".encode('utf-8').decode('utf-8')}
if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

requirements.txt

fastapi
uvicorn
numpy==1.23.5
llama-index==0.10.62
llama-index-core==0.10.28
llama-index-embeddings-dashscope==0.1.3
llama-index-llms-dashscope==0.1.2
llama-index-vector-stores-chroma==0.1.6
aiohttp

Démo LangChain

llm_app.py

from fastapi import FastAPI
from langchain.llms.fake import FakeListLLM
import uvicorn
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
app = FastAPI()
llm = FakeListLLM(responses=["I'll callback later.", "You 'console' them!"])
template = """Question: {question}
Answer: Let's think step by step."""
prompt = PromptTemplate(template=template, input_variables=["question"])
llm_chain = LLMChain(prompt=prompt, llm=llm)
question = "What NFL team won the Super Bowl in the year Justin Beiber was born?"
@app.get("/")
def call_langchain():
    res = llm_chain.run(question)
    return {"data": res}
if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

requirements.txt

fastapi
uvicorn
langchain
langchain_community

Démo Dify

Vous pouvez rapidement créer une application Dify en suivant les instructions de la rubrique Créer un assistant Q&A IA personnalisé basé sur le web à l'aide de Dify.