Elastic
Jina AI
Modèles
API
keyboard_arrow_down
Reader
Convertissez n'importe quelle URL en Markdown pour un meilleur grounding des LLM.
Embeddings
Embeddings multimodales et multilingues.
Reclasseur
Outil de reclassement pour optimiser la pertinence des résultats de recherche.
MCP
terminal
CLI
article
llms.txt
smart_toy
Agents
data_object
Schéma
menu_book
Documents
Se connecter
login
Récupération des tickets de support Jira
Avantages de Jina Embeddings et Reranker
Blog technique
avril 10, 2024

Récupérer des tickets Jira avec Jina Reranker et Haystack 2.0

Découvrez comment utiliser Jina Reranker et Embeddings avec Haystack pour créer votre propre moteur de recherche de tickets Jira, optimisant ainsi vos opérations et évitant de perdre du temps à créer des tickets en double.
Graphic with "Reranker" and "Haystack by deepset" on a black background with teal decorative elements.
Francesco Kruk • 10 minutes lues

Suite à l'intégration de Jina Embeddings dans Haystack 2.0 de Deepset et à la sortie de Jina Reranker, nous sommes ravis d'annoncer que Jina Reranker est désormais également disponible via l'extension Jina Haystack.

Jina AI | Haystack
Utilisez les derniers modèles d'embedding Jina AI
HaystackAuthors deepset
Reranker API
Maximisez facilement la pertinence des recherches et la précision du RAG

Haystack est un framework complet qui vous accompagne à chaque étape du cycle de vie d'un projet GenAI. Que vous souhaitiez effectuer une recherche de documents, de la génération augmentée par récupération (RAG), répondre à des questions ou générer des réponses, Haystack peut orchestrer des modèles d'embedding et des LLM à la pointe de la technologie dans des pipelines pour créer des applications NLP de bout en bout et résoudre vos cas d'usage.

Haystack | Haystack
Haystack, le framework IA open-source composable
Haystack

Dans cet article, nous allons vous montrer comment les utiliser pour créer votre propre moteur de recherche de tickets Jira afin d'optimiser vos opérations et ne plus jamais perdre de temps à créer des tickets en double.

Pour suivre ce tutoriel, vous aurez besoin d'une clé API Jina Reranker. Vous pouvez en créer une avec un quota d'essai gratuit d'un million de tokens sur le site web de Jina Reranker.

💡
Vous pouvez suivre dans Colab ou en téléchargeant le notebook.

tagRécupération des tickets de support Jira

Toute équipe gérant un projet complexe a déjà connu la frustration de vouloir signaler un problème sans savoir si un ticket existe déjà pour celui-ci.

Dans ce tutoriel, nous allons vous montrer comment créer facilement un outil utilisant Jina Reranker et les pipelines Haystack, qui suggère les tickets potentiellement en double lors de la création d'un nouveau ticket.

  • En saisissant un ticket à vérifier par rapport à tous les tickets existants, le pipeline récupérera d'abord de la base de données tous les problèmes connexes.
  • Il supprimera ensuite le ticket initial de la liste (s'il existait déjà dans la base de données) et tout ticket enfant (c'est-à-dire les tickets dont l'ID parent correspond au ticket original).
  • La sélection finale ne comprend désormais que les problèmes qui pourraient couvrir le même sujet que le ticket original mais n'ont pas été marqués comme tels dans la base de données via leurs IDs. Ces tickets sont reclassés pour assurer une pertinence maximale et vous permettre d'identifier les entrées en double dans la base de données.

tagObtention du jeu de données

Pour implémenter notre solution, nous avons choisi tous les tickets Jira "En cours" du projet Apache Zookeeper. Il s'agit d'un service open-source pour coordonner les processus d'applications distribuées.

Nous avons placé les tickets dans un fichier JSON pour les rendre plus pratiques. Veuillez télécharger le fichier dans votre espace de travail.

tagConfiguration des prérequis

Pour installer les dépendances, exécutez :

pip install --q chromadb haystack-ai jina-haystack chroma-haystack

Pour définir la clé API, configurez-la comme variable d'environnement :

import os
import getpass

os.environ["JINA_API_KEY"] = getpass.getpass()
💡
Si vous exécutez ce code via le notebook, getpass.getpass() vous invitera à saisir la clé API sous le bloc de code correspondant. Vous pouvez saisir la clé à cet endroit et appuyer sur Entrée pour reprendre le tutoriel. Si vous préférez, vous pouvez également remplacer getpass.getpass() par la clé API elle-même.

tagConstruction du pipeline d'indexation

Le pipeline d'indexation va prétraiter les tickets, les transformer en vecteurs et les stocker. Nous utiliserons le Chroma DocumentStore comme base de données vectorielle pour stocker les embeddings vectoriels, via l'intégration Chroma Document Store Haystack.

from haystack_integrations.document_stores.chroma import ChromaDocumentStore

document_store = ChromaDocumentStore()

Nous allons commencer par définir notre préprocesseur de données personnalisé pour ne considérer que les champs de document pertinents et supprimer toutes les entrées vides :

import json
from typing import List
from haystack import Document, component

relevant_keys = ['Summary', 'Issue key', 'Issue id', 'Parent id', 'Issue type', 'Status', 'Project lead', 'Priority', 'Assignee', 'Reporter', 'Creator', 'Created', 'Updated', 'Last Viewed', 'Due Date', 'Labels',
                 'Description', 'Comment', 'Comment__1', 'Comment__2', 'Comment__3', 'Comment__4', 'Comment__5', 'Comment__6', 'Comment__7', 'Comment__8', 'Comment__9', 'Comment__10', 'Comment__11', 'Comment__12',
                 'Comment__13', 'Comment__14', 'Comment__15']

@component
class RemoveKeys:
    @component.output_types(documents=List[Document])
    def run(self, file_name: str):
        with open(file_name, 'r') as file:
            tickets = json.load(file)
        cleaned_tickets = []
        for t in tickets:
            t = {k: v for k, v in t.items() if k in relevant_keys and v}
            cleaned_tickets.append(t)
        return {'documents': cleaned_tickets}

Nous devons ensuite créer un convertisseur JSON personnalisé pour transformer les tickets en objets Document que Haystack peut comprendre :

@component
class JsonConverter:
    @component.output_types(documents=List[Document])
    def run(self, tickets: List[Document]):
        tickets_documents = []
        for t in tickets:
            if 'Parent id' in t:
                t = Document(content=json.dumps(t), meta={'Issue key': t['Issue key'], 'Issue id': t['Issue id'], 'Parent id': t['Parent id']})
            else:
                t = Document(content=json.dumps(t), meta={'Issue key': t['Issue key'], 'Issue id': t['Issue id'], 'Parent id': ''})
            tickets_documents.append(t)
        return {'documents': tickets_documents}

Enfin, nous intégrons les Documents et écrivons ces embeddings dans le ChromaDocumentStore :

from haystack import Pipeline

from haystack.components.writers import DocumentWriter
from haystack_integrations.components.retrievers.chroma import ChromaEmbeddingRetriever
from haystack.document_stores.types import DuplicatePolicy

from haystack_integrations.components.embedders.jina import JinaDocumentEmbedder

retriever = ChromaEmbeddingRetriever(document_store=document_store)
retriever_reranker = ChromaEmbeddingRetriever(document_store=document_store)

indexing_pipeline = Pipeline()
indexing_pipeline.add_component('cleaner', RemoveKeys())
indexing_pipeline.add_component('converter', JsonConverter())
indexing_pipeline.add_component('embedder', JinaDocumentEmbedder(model='jina-embeddings-v2-base-en'))
indexing_pipeline.add_component('writer', DocumentWriter(document_store=document_store, policy=DuplicatePolicy.SKIP))

indexing_pipeline.connect('cleaner', 'converter')
indexing_pipeline.connect('converter', 'embedder')
indexing_pipeline.connect('embedder', 'writer')

indexing_pipeline.run({'cleaner': {'file_name': 'tickets.json'}})

Cela devrait créer une barre de progression et afficher un bref JSON contenant des informations sur ce qui a été stocké :

Calculating embeddings: 100%|██████████| 1/1 [00:01<00:00,  1.21s/it]
{'embedder': {'meta': {'model': 'jina-embeddings-v2-base-en',
   'usage': {'total_tokens': 20067, 'prompt_tokens': 20067}}},
 'writer': {'documents_written': 31}}

tagConstruire le Pipeline de Requête

Créons un pipeline de requête pour pouvoir commencer à comparer les tickets. Dans Haystack 2.0, les retrievers sont étroitement couplés aux DocumentStores. Si nous passons le document store dans le retriever que nous avons initialisé précédemment, ce pipeline peut accéder aux documents que nous avons générés et les transmettre au reranker. Le reranker compare ensuite ces documents directement avec la question et les classe selon leur pertinence.

Nous définissons d'abord le nettoyeur personnalisé pour supprimer les tickets récupérés qui contiennent soit le même ID de problème, soit le même ID parent que le problème passé en requête :

from typing import Optional

@component
class RemoveRelated:
    @component.output_types(documents=List[Document])
    def run(self, tickets: List[Document], query_id: Optional[str]):
        retrieved_tickets = []
        for t in tickets:
            if not t.meta['Issue id'] == query_id and not t.meta['Parent id'] == query_id:
                retrieved_tickets.append(t)
        return {'documents': retrieved_tickets}

Nous incorporons ensuite la requête, récupérons les documents pertinents, nettoyons la sélection, et enfin la reclassons :

from haystack_integrations.components.embedders.jina import JinaTextEmbedder
from haystack_integrations.components.rankers.jina import JinaRanker

query_pipeline_reranker = Pipeline()
query_pipeline_reranker.add_component('query_embedder_reranker', JinaTextEmbedder(model='jina-embeddings-v2-base-en'))
query_pipeline_reranker.add_component('query_retriever_reranker', retriever_reranker)
query_pipeline_reranker.add_component('query_cleaner_reranker', RemoveRelated())
query_pipeline_reranker.add_component('query_ranker_reranker', JinaRanker())

query_pipeline_reranker.connect('query_embedder_reranker.embedding', 'query_retriever_reranker.query_embedding')
query_pipeline_reranker.connect('query_retriever_reranker', 'query_cleaner_reranker')
query_pipeline_reranker.connect('query_cleaner_reranker', 'query_ranker_reranker')
Diagramme de flux décrivant un processus de traitement des requêtes avec des fonctions comme 'text', 'query_embedder_reranker', 'meta'.

Pour mettre en évidence la différence causée par le reranker, nous avons analysé le même pipeline sans l'étape finale de reclassement (le code correspondant a été omis dans ce billet par souci de lisibilité mais peut être trouvé dans le notebook) :

Organigramme détaillant un processus de recherche de texte avec les composants 'query_embedding', 'query_retriever' et 'query_cleaner'.

Pour comparer les résultats de ces deux pipelines, nous définissons maintenant notre requête sous la forme d'un ticket existant, ici "ZOOKEEPER-3282" :

query_ticket_key = 'ZOOKEEPER-3282'

with open('tickets.json', 'r') as file:
    tickets = json.load(file)

for ticket in tickets:
    if ticket['Issue key'] == query_ticket_key:
        query = str(ticket)
        query_ticket_id = ticket['Issue id']

Il concerne "une grande refonte des documetations" [sic]. Vous verrez que, malgré la faute d'orthographe, Jina Reranker récupérera correctement les tickets similaires.

{
    "Summary": "a big refactor for the documetations"
    "Issue key": "ZOOKEEPER-3282"
    "Issue id:: 13216608
    "Parent id": ""
    "Issue Type": "Task"
    "Status": "In Progress"
    "Project lead": "phunt"
    "Priority": "Major"
    "Assignee": "maoling"
    "Reporter": "maoling"
    "Creator": "maoling"
    "Created": "19/Feb/19 11:50"
    "Updated": "04/Aug/19 12:48"
    "Last Viewed": "12/Mar/24 11:56"
    "Description": "Hi guys: I'am working on doing a big refactor for the documetations.it aims to - 1.make a better reading experiences and help users know more about zookeeper quickly,as good as other projects' doc(e.g redis,hbase). - 2.have less changes to diff with the original docs as far as possible. - 3.solve the problem when we have some new features or improvements,but cannot find a good place to doc it.   The new catalog may looks kile this: * is new one added. ** is the one to keep unchanged as far as possible. *** is the one modified. -------------------------------------------------------------- |---Overview    |---Welcome ** [1.1]    |---Overview ** [1.2]    |---Getting Started ** [1.3]    |---Release Notes ** [1.4] |---Developer    |---API *** [2.1]    |---Programmer's Guide ** [2.2]    |---Recipes *** [2.3]    |---Clients * [2.4]    |---Use Cases * [2.5] |---Admin & Ops    |---Administrator's Guide ** [3.1]    |---Quota Guide ** [3.2]    |---JMX ** [3.3]    |---Observers Guide ** [3.4]    |---Dynamic Reconfiguration ** [3.5]    |---Zookeeper CLI * [3.6]    |---Shell * [3.7]    |---Configuration flags * [3.8]    |---Troubleshooting & Tuning  * [3.9] |---Contributor Guidelines    |---General Guidelines * [4.1]    |---ZooKeeper Internals ** [4.2] |---Miscellaneous    |---Wiki ** [5.1]    |---Mailing Lists ** [5.2] -------------------------------------------------------------- The Roadmap is: 1.(I pick up it : D)  1.1 write API[2.1], which includes the:    1.1.1  original API Docs which is a Auto-generated java doc,just give a link.    1.1.2. Restful-api (the apis under the /zookeeper-contrib-rest/src/main/java/org/apache/zookeeper/server/jersey/resources)  1.2 write Clients[2.4], which includes the:      1.2.1 C client      1.2.2 zk-python, kazoo      1.2.3 Curator etc.......      look at an example from: https://redis.io/clients # write Recipes[2.3], which includes the:  - integrate "Java Example" and "Barrier and Queue Tutorial"(Since some bugs in the examples and they are obsolete,we may delete something) into it.  - suggest users to use the recipes implements of Curator and link to the Curator's recipes doc.   # write Zookeeper CLI[3.6], which includes the:  - about how to use the zk command line interface [./zkCli.sh]    e.g ls /; get ; rmr;create -e -p etc.......  - look at an example from redis: https://redis.io/topics/rediscli   # write shell[3.7], which includes the:   - list all usages of the shells under the zookeeper/bin. (e.g zkTxnLogToolkit.sh,zkCleanup.sh)   # write Configuration flags[3.8], which includes the:   - list all usages of configurations properties(e.g zookeeper.snapCount):   - move the original Advanced Configuration part of zookeeperAdmin.md into it.     look at an example from:https://coreos.com/etcd/docs/latest/op-guide/configuration.html    # write Troubleshooting & Tuning[3.9], which includes the:   - move the original "Gotchas: Common Problems and Troubleshooting" part of Administrator's Guide.md into it.   - move the original "FAQ" into into it.   - add some new contents (e.g https://www.yumpu.com/en/document/read/29574266/building-an-impenetrable-zookeeper-pdf-github).   look at an example from:https://redis.io/topics/problems                             https://coreos.com/etcd/docs/latest/tuning.html   # write General Guidelines[4.1], which includes the:  - move the original "Logging" part of ZooKeeper Internals into it as the logger specification.  - write specifications about code, git commit messages,github PR  etc ...    look at an example from:    http://hbase.apache.org/book.html#hbase.commit.msg.format   # write Use Cases[2.5], which includes the:  - just move the context from: https://cwiki.apache.org/confluence/display/ZOOKEEPER/PoweredBy into it.  - add some new contents.(e.g Apache Projects:Spark;Companies:twitter,fb)   -------------------------------------------------------------- BTW: - Any insights or suggestions are very welcomed.After the dicussions,I will create a series of tickets(An umbrella) - Since these works can be done parallelly, if you are interested in them, please don't hesitate,just assign to yourself, pick it up. (Notice: give me a ping to avoid the duplicated work)."
}

Enfin, nous exécutons le pipeline de requête. Dans ce cas, il récupère 20 tickets, élimine les entrées liées à l'ID, les reclasse et produit la sélection finale des 10 problèmes les plus pertinents.

Avant l'étape de reclassement, la sortie comprend 17 tickets :

Rank Issue ID Issue Key Summary
1 13191544 ZOOKEEPER-3170 Umbrella for eliminating ZooKeeper flaky tests
2 13400622 ZOOKEEPER-4375 Quota cannot limit the specify value when multiply clients create/set znodes
3 13249579 ZOOKEEPER-3499 [admin server way] Add a complete backup mechanism for zookeeper internal
4 13295073 ZOOKEEPER-3775 Wrong message in IOException
5 13268474 ZOOKEEPER-3617 ZK digest ACL permissions gets overridden
6 13296971 ZOOKEEPER-3787 Apply modernizer-maven-plugin to build
7 13265507 ZOOKEEPER-3600 support the complete linearizable read and multiply read consistency level
8 13222060 ZOOKEEPER-3318 [CLI way]Add a complete backup mechanism for zookeeper internal
9 13262989 ZOOKEEPER-3587 Add a documentation about docker
10 13262130 ZOOKEEPER-3578 Add a new CLI: multi
11 13262828 ZOOKEEPER-3585 Add a documentation about RequestProcessors
12 13262494 ZOOKEEPER-3583 Add new apis to get node type and ttl time info
13 12998876 ZOOKEEPER-2519 zh->state should not be 0 while handle is active
14 13536435 ZOOKEEPER-4696 Update for Zookeeper latest version
15 13297249 ZOOKEEPER-3789 fix the build warnings about @see,@link,@return found by IDEA
16 12728973 ZOOKEEPER-1983 Append to zookeeper.out (not overwrite) to support logrotation
17 12478629 ZOOKEEPER-915 Errors that happen during sync() processing at the leader do not get propagated back to the client.

Après avoir inclus le reclasseur, nous exécutons maintenant le pipeline de requêtes :

result = query_pipeline_reranker.run(data={'query_embedder_reranker':{'text': query},
                                  'query_retriever_reranker': {'top_k': 20},
                                  'query_cleaner_reranker': {'query_id': query_ticket_id},
                                  'query_ranker_reranker': {'query': query, 'top_k': 10}
                                  }
                            )

for idx, res in enumerate(result['query_ranker_reranker']['documents']):
    print('Doc {}:'.format(idx + 1), res)

La sortie finale correspond aux 10 tickets les plus pertinents :

Rank Issue ID Issue Key Summary
1 13262989 ZOOKEEPER-3587 Add a documentation about docker
2 13265507 ZOOKEEPER-3600 support the complete linearizable read and multiply read consistency level
3 13249579 ZOOKEEPER-3499 [admin server way] Add a complete backup mechanism for zookeeper internal
4 12478629 ZOOKEEPER-915 Errors that happen during sync() processing at the leader do not get propagated back to the client.
5 13262828 ZOOKEEPER-3585 Add a documentation about RequestProcessors
6 13297249 ZOOKEEPER-3789 fix the build warnings about @see,@link,@return found by IDEA
7 12998876 ZOOKEEPER-2519 zh->state should not be 0 while handle is active
8 13536435 ZOOKEEPER-4696 Update for Zookeeper latest version
9 12728973 ZOOKEEPER-1983 Append to zookeeper.out (not overwrite) to support logrotation
10 13222060 ZOOKEEPER-3318 [CLI way]Add a complete backup mechanism for zookeeper internal

tagAvantages de Jina Embeddings et Reranker

Pour résumer ce tutoriel, nous avons construit un outil d'identification des tickets en double basé sur Jina Embeddings, Jina Reranker et Haystack 2.0. Les résultats ci-dessus montrent clairement la nécessité d'utiliser à la fois Jina Embeddings pour récupérer les documents pertinents via la recherche vectorielle, et Jina Reranker pour obtenir finalement le contenu le plus pertinent.

Si nous prenons, par exemple, les deux problèmes relatifs à l'ajout de documentation, c'est-à-dire "ZOOKEEPER-3585" et "ZOOKEEPER-3587", nous constatons qu'après l'étape de récupération, ils sont tous deux correctement inclus aux positions 11 et 9 respectivement. Après le reclassement des documents, ils se trouvent maintenant tous deux parmi les 5 documents les plus pertinents aux positions 5 et 1 respectivement, montrant une amélioration significative.

En intégrant les deux modèles dans les pipelines de Haystack, l'outil complet est prêt à l'emploi. Cette combinaison fait de l'extension Jina Haystack la solution parfaite pour votre application.

Catégories:
Blog technique
rss_feed

En savoir plus
mars 11, 2026 • 7 minutes lues
Bootstrapping Audio Embeddings from Multimodal LLMs
Han Xiao
Abstract illustration of a sound wave or heartbeat, formed by blue, orange, and gray dots on a white background.
mars 06, 2026 • 6 minutes lues
Identifying Embedding Models from Raw Numerical Values
Han Xiao
Fingerprint illustration made from numbers, showcasing digital and high-tech design on a light background.
septembre 09, 2025 • 11 minutes lues
Multimodal Embeddings in Llama.cpp and GGUF
Andrei Ungureanu
Alex C-G
Cartoon llama in the center of a white background, emitting laser-like beams from its eyes. The illustration creates a playfu
Langue / thème actuel
Search Foundation
Reader
Embeddings
Reclasseur
Obtenir la clé API Jina
Limite de débit
À propos de nous
Actualités
Télécharger le logo Jina
open_in_new
Télécharger le logo Elastic
open_in_new
Statut de l'API
Elastic © 2026.SécuritéTermes et conditionsConfidentialitéGérer les cookiesNe vendez ni ne partagez mes informations personnelles
Ce site web et l'ensemble de son contenu, de ses logiciels, produits et services sont destinés exclusivement à un usage professionnel. Aucun usage à des fins de consommation n'est prévu.