Große Sprachmodelle (Large Language Models, LLMs) sind unglaublich leistungsfähig, aber ihr Wissen ist auf ihre Trainingsdatensätze beschränkt. Bei der Beantwortung von Fragen, insbesondere zu spezifischen, sich entwickelnden oder geschützten Informationen, können LLMs halluzinieren oder allgemeine, irrelevante Antworten liefern. Retrieval Augmented Generation (RAG) hilft, indem es dem LLM relevante abgerufene Informationen aus externen Datenquellen zur Verfügung stellt.
Allerdings sind nicht alle RAG-Produkte gleich. Corrective Retrieval Augmented Generation (cRAG) baut nicht einfach auf dem traditionelleren RAG auf, sondern stellt eine deutliche Verbesserung dar. Sie ist so konzipiert, dass sie zuverlässiger ist, indem sie die Qualität und Relevanz der abgerufenen Ergebnisse bewertet. Wenn der Kontext schwach oder irrelevant ist oder aus einer nicht vertrauenswürdigen Quelle stammt, versucht cRAG, durch Korrekturmaßnahmen bessere Informationen zu finden, oder verweigert explizit die Antwort, anstatt eine Antwort zu erfinden. Diese Technik macht cRAG-Systeme zuverlässiger und vertrauenswürdiger für entscheidende Anwendungen wie die Beantwortung richtlinienbezogener Fragen.
In diesem Tutorial erfahren Sie, wie Sie ein robustes korrektives RAG-System (cRAG) aufbauen, indem Sie IBM® Granite®-Modelle auf Watsonx® und LangChain verwenden. Ähnliche Frameworks wie LlamaIndex oder LangGraph können ebenfalls zum Aufbau komplexer RAG-Abläufe mit unterschiedlichen Knoten verwendet werden. Techniken wie Fine-Tuning können die spezifische LLM-Leistung für domänenspezifisches RAG weiter verbessern. LLMs wie die von OpenAI (zum Beispiel GPT-Modelle wie ChatGPT) sind ebenfalls beliebte Optionen für solche Agenten, obwohl sich dieses Tutorial auf IBM Granite konzentriert.
Hier konzentrieren wir uns auf einen Anwendungsfall: die Beantwortung von Fragen zu einem bestimmten Versicherungsvertrag (PDF). Dieses Tutorial führt Sie durch die Implementierung eines komplexen RAG-Algorithmus, der:
Informationen abruft aus Ihrem eigenen PDF-Dokument.
Wenn die internen Dokumente nicht ausreichen, um die Antwort zu generieren, kann der Agent als Ausweichlösung eine externe Websuche (Tavily) verwenden.
Der Agent filtert auf intelligente Weise irrelevante externe Ergebnisse heraus, sodass die Antworten auf private Richtlinien zugeschnitten sind.
Der Agent gibt klare, begrenzte Antworten mit Teilinformationen, sofern diese verfügbar sind, oder lehnt Anfragen eindeutig ab, wenn der Kontext fehlt.
Dieses Tutorial demonstriert die Erstellung eines Versicherungsanfrage-Agenten, der Versicherungsdokumente (eine PDF-Broschüre) analysiert und Benutzeranfragen präzise beantwortet. Wir verwenden IBM Granite-Modelle und LangChain, um den Agenten mit robusten Abfrage- und Verifizierungsschritten zu entwickeln, die qualitativ hochwertige, quellengestützte Antworten gewährleisten.
Lassen Sie uns untersuchen, wie die wichtigsten Prinzipien einer zuverlässigen RAG in unserem Anwendungsfall zum Tragen kommen.
Interne Wissensdatenbank (PDF): Die primäre Quelle der Wahrheit für den Makler ist die PDF-Datei Ihrer Versicherungspolice. Es wandelt dieses Dokument in einen durchsuchbaren Vektorspeicher um.
Fallback für externe Suche (Tavily): Sollte die interne Wissensdatenbank nicht über ausreichende Informationen verfügen, kann der Mitarbeiter über Tavily externe Webquellen konsultieren. Tavily ist eine Suchmaschine, die speziell für KI-Agenten und LLMs entwickelt wurde und durch ihre Anwendungsprogrammierschnittstelle (API) für RAG-basierte Anwendungen eine schnellere Abfrage in Echtzeit ermöglicht.
Bewertung des Kontexts: Der LLM-basierte Retrieval-Evaluator (der als Bewerter fungiert) bewertet die Relevanz der aus Ihrer internen PDF-Datei abgerufenen Elemente und stellt gleichzeitig sicher, dass nur qualitativ hochwertige abgerufene Elemente berücksichtigt werden.
Umformulierung von Suchanfragen: Bei der Websuche kann der Agent die Anfrage des Benutzers umformulieren, um die Chancen zu erhöhen, relevante externe Informationen zu finden.
Quellenüberprüfung: Eine LLM-gestützte Prüfung bewertet, ob externe Web-Suchergebnisse für eine private Versicherungspolice relevant sind, indem sie allgemeine Informationen oder Details zu öffentlichen Gesundheitsprogrammen (wie Medi-Cal) herausfiltert. Diese Funktion verhindert die Generierung irreführender Antworten und ermöglicht eine Selbstkorrektur, was bei der Wissensverfeinerung hilft.
Eingeschränkte Generierung: Die abschließende Aufforderung an das LLM weist es ausdrücklich an, nur den bereitgestellten Kontext zu verwenden, präzise Antworten zu geben, anzugeben, wenn Informationen nicht verfügbar sind, oder Teilantworten mit expliziten Einschränkungen zu liefern. Diese Funktion verbessert die Anpassungsfähigkeit und Zuverlässigkeit der generierten Antworten.
Sie benötigen ein IBM Cloud-Konto, um für das Erstellen eines watsonx.ai-Projekts. Stellen Sie sicher, dass Sie sowohl auf Ihren watsonx API-Schlüssel als auch auf Ihre Projekt-ID zugreifen können. Sie benötigen außerdem einen API -Schlüssel für Tavily KI für Websuchfunktionen.
Sie können zwar aus mehreren Tools wählen, aber dieses Tutorial führt Sie durch die Einrichtung eines IBM Kontos für die Verwendung eines Jupyter Notebook.
Dieser Schritt öffnet eine Notebook-Umgebung, in die Sie den Code aus diesem Tutorial kopieren können. Alternativ können Sie dieses Notebook auf Ihr lokales System herunterladen und als Asset in Ihr watsonx.ai-Projekt hochladen. Weitere Granite-Tutorials finden Sie in der IBM Granite-Community. Dieses Tutorial ist auch auf Github verfügbar.
Um mit dem LangChain-Framework zu arbeiten und IBM WatsonxLLM zu integrieren, müssen wir einige wichtige Bibliotheken installieren. Beginnen wir mit der Installation der erforderlichen Pakete. Dieses Set umfasst langchain für das RAG-Framework, langchain-ibm für die Watsonx-Integration, faiss-cpu für die effiziente Speicherung von Vektoren, PyPDF2 für die Verarbeitung von PDF-Dateien, sentence-transformers für das Abrufen einer Einbettung und requests für Web-API-Aufrufe. Diese Bibliotheken sind für die Anwendung von maschinellem Lernen und NLP-Lösungen von entscheidender Bedeutung.
Hinweis: Es ist keine GPU erforderlich, aber die Ausführung kann auf CPU-basierten Systemen langsamer sein. Dieser Schritt öffnet eine Notebook-Umgebung, in die Sie den Code aus diesem Tutorial kopieren können. Dieses Tutorial ist auch auf GitHub verfügbar.
Importieren Sie als Nächstes alle erforderlichen Module und stellen Sie Ihre API-Schlüssel für watsonx und Tavily zusammen mit Ihrer watsonx Projekt-ID sicher bereit.
os hilft bei der Zusammenarbeit mit dem Betriebssystem.
io ermöglicht die Arbeit mit Datenströmen.
getpass verwendet eine sichere Methode, um sensible Informationen wie API-Schlüssel zu erfassen und zeigt keine Eingaben auf dem Bildschirm an.
PyPDF2.PdfReader ermöglicht die Extraktion von Inhalten aus PDFs.
langchain_ibm.WatsonxLLM ermöglicht es uns, das IBM Watsonx Granite LLM einfach innerhalb des LangChain-Frameworks zu verwenden.
langchain.embeddings.HuggingFaceEmbeddings nimmt ein HuggingFace-Modell und erzeugt die Einbettungen, die für die semantische Suche wichtig sind.
langchain.vectorstores.FAISS ist eine Bibliothek für effiziente Vektor-Speicher und Ähnlichkeitssuche, die es uns ermöglicht, einen Vektorindex zu erstellen und abzufragen.
langchain.text_splitter.RecursiveCharacterTextSplitter hilft dabei, große Textteile in kleinere Stücke zu zerlegen, die für die Verarbeitung von Dokumenten benötigt werden, die sonst nicht in den Speicher passen würden.
langchain.schema.Document stellt eine beliebige Texteinheit mit zugehörigen Metadaten dar und macht es zu einem Baustein in langchain.
requests wird verwendet, um HTTP-Anfragen extern an APIs zu senden.
botocore.client.Config ist eine Konfigurationsklasse, mit der Konfigurationseinstellungen für einen AWS/IBM Cloud Object Storage-Client definiert werden.
ibm_boto3 ist das IBM Cloud Object Storage SDK für Python, das die Interaktion mit Cloud Object Storage unterstützt.
langchain.prompts.PromptTemplate bietet eine Möglichkeit, wiederverwendbare, strukturierte Prompts für Sprachmodelle zu erstellen.
langchain.tools.BaseTool ist die Basisklasse, aus der Sie benutzerdefinierte Tools erstellen, die den LangChain-Agenten zur Verwendung übergeben werden können.
In diesem Schritt werden alle Werkzeuge und Module eingerichtet, die wir benötigen, um Text zu verarbeiten, Einbettungen zu erstellen, sie in einer Vektordatenbank zu speichern und mit watsonx LLM von IBM zu interagieren. Es enthält alle Teile, die für den Aufbau eines realen RAG-Systems erforderlich sind, das eine Reihe von Datentypen beschaffen, abfragen und durchsuchen kann.
In diesem Schritt laden wir die PDF-Versicherungspolice aus IBM Cloud Object Storage. Der Code liest die PDF-Datei, liest den Textinhalt und teilt den Text in kleinere und überschaubare Abschnitte auf. Diese Blöcke werden in numerische Einbettungen umgewandelt und in einem FAISS-Vektorspeicher abgelegt, der uns für die spätere semantische Ähnlichkeitssuche im lokalen Kontext vorbereitet, um die Suchergebnisse zu optimieren.
ibm_boto3.client ermöglicht es dem Client, mit IBM Cloud Object Storage zu interagieren.
Bucket ist der Name des Cloud Object Storage-Buckets, der die PDF enthält.
object_key ist der Name der PDF-Datei im Cloud Object Storage-Bucket.
cos_client.get_object(...).read() ruft den Inhalt der PDF-Datei im Cloud Object Storage als Bytes ab.
io.BytesIO konvertiert die PDF-Rohbytes in einen In-Memory-Binärstream in einem Format, das von PdfReader verwendet werden kann.
PdfReader erstellt ein Objekt, das Text aus der PDF-Datei analysieren und extrahieren kann.
page.extract_text() extrahiert den Text einer einzelnen Seite in der PDF-Datei.
RecursiveCharacterTextSplitter ist so konfiguriert, dass der extrahierte Text in Abschnitte von 500 Zeichen mit einer Überlappung von 50 Zeichen aufgeteilt wird, sodass alles im Kontext bleibt.
splitter.split_text(text) führt die Aufteilung aller Seiten des PDF-Textes in kleinere Teile durch.
HuggingFaceEmbeddings lädt ein Satzumwandlungsmodell, das vorab trainiert wurde, um die Textstücke in dichte Vektordarstellungen umzuwandeln.
FAISS.from_texts(chunks, embeddings) erstellt einen In-Memory-FAISS-Index, der es ermöglicht, Textabschnitte anhand ihrer semantischen Ähnlichkeiten zu durchsuchen.
Dieser Schritt behandelt die vollständige Aufnahme eines PDF-Dokuments aus der Cloud in LLM-fähigen Text und eine komfortable Indizierung zum Abrufen in Echtzeit.
In diesem Schritt konfigurieren Sie das IBM Granite LLM so, dass es die Argumentation Ihres Agenten steuert und es in die Tavily-Websuchfunktion integriert. Die Parameter des LLM sind für sachliche, stabile Antworten eingerichtet.
WatsonxLLM instanziiert den LLM-Wrapper für IBM watsonx und ermöglicht die Interaktion mit Granite-Modellen.
model_id="ibm/granite-3-2b-instruct" ist das IBM Granite-Modell (ein Instruktionsmodell mit 2,7 Milliarden Parametern), das für anweisungsbasierte generative KI-Aufgaben entwickelt wurde.
class TavilySearch(BaseTool) definiert ein benutzerdefiniertes LangChain-Tool zum Ausführen von Websuchen mithilfe der Tavily-API.
tavily_tool = TavilySearch() erstellt eine ausführbare Instanz des benutzerdefinierten Tavily-Suchwerkzeugs.
Wenn wir watsonxLLM initialisieren, werden die url-, apikey- und project_id-Werte aus unseren zuvor eingerichteten Zugangsdaten übergeben, um sich zu authentifizieren und eine Verbindung mit dem Dienst herzustellen. Parameter wie „max_new_tokens“: 300 begrenzen die Antwortlänge und „temperature“: 0,2 kontrolliert die Output-Kreativität und begünstigt deterministischere Ergebnisse.
Die TavilySearch-Klassendefinition enthält eine Beschreibung ihrer Funktion. Ihre Logik ist in der Methode def _run(self, Queries: streng) enthalten. Bei dieser Methode stellen wir eine HTTP-POST-Anfrage an den Tavily-API-Endpunkt und fügen den TAVILY_API_KEY und die Suchanfrage in die JSON-Nutzdaten ein. Anschließend überprüfen wir mit response.raise_for_status(), ob HTTP-Fehler aufgetreten sind,und analysieren die JSON-Antwort, um auf den Inhaltsausschnitt des ersten Suchergebnisses zuzugreifen.
In diesem Schritt wird das Sprachmodell für die Textgenerierung eingerichtet, und es wird ein externes Websuchtool verwendet, um das Wissen über das Sprachmodell zu erweitern.
Dieser Schritt definiert die verschiedenen Prompt-Vorlagen, die das Verhalten des LLM in den verschiedenen Phasen des RAG-Prozesses steuern. Dieser Ansatz umfasst Prompts zur Bewertung der Relevanz interner Dokumentenabschnitte, die Umschreibung von Benutzerabfragen für eine bessere Websuche und einen kritischen neuen Prompt zur Überprüfung der Quelle der Ergebnisse. Es werden auch Hilfsfunktionen für die Bewertung von Chunks und deren Abrufen aus dem Vektorspeicher definiert.
Dieser Schritt definiert die verschiedenen Prompt-Vorlagen, die das Verhalten des LLM in den verschiedenen Phasen des RAG-Prozesses steuern. Eingabeaufforderungen zur Bewertung der Relevanz interner Dokumentenblöcke, Umschreibung von Benutzerabfragen für eine bessere Websuche und ein entscheidendes neues Prompt zur Überprüfung, dass die Quelle der Web-Suchergebnisse enthalten ist. Es werden auch Hilfsfunktionen für die Bewertung von Chunks und deren Abrufen aus dem Vektorspeicher definiert.
PromptTemplate.from_template ist ein Dienstprogramm von LangChain, um eine wiederverwendbare Vorlage für die Erstellung von Prompts zu erstellen.
scoring_prompt_template definiert einen Prompt, der das LLM anweist, als Bewerter zu fungieren und einem bestimmten Kontextabschnitt auf der Grundlage einer Frage einen Relevanzwert (0–5) zuzuweisen.
rewrite_prompt_template definiert einen Prompt, der das LLM dazu anleitet, die ursprüngliche Frage eines Benutzers für die Suche zu verbessern oder klarer zu machen.
CONTEXT_SOURCE_VERIFICATION_PROMPT definiert einen Prompt, der das LLM anweist, zu überprüfen, ob ein Textabschnitt (z. B. aus einer Websuche) aus einem privaten Richtlinienkontext oder einer allgemeinen oder öffentlichen Quelle stammt.
def score_chunks(chunks, query) definiert eine Funktion, die eine Liste von Textabschnitten und eine Abfrage verwendet, die dann das LLM verwendet, um die Relevanz jedes Abschnitts zu bewerten.
def reach_from_vectorstore(query) definiert eine Funktion zum Abrufen der ähnlichsten Dokumente aus dem FAISS Vektorspeicher.
Innerhalb der Funktion score_chunks wird eine leere Trefferliste initialisiert. Für jeden Chunk wird die scoring_prompt_template mit der spezifischen Abfrage und dem Chunk formatiert. Dieser formatierte Prompt wird dann an das LLM gesendet und die Antwort wird entfernt. Die Funktion versucht, die ganzzahlige Punktzahl (eine binäre Punktzahl, wenn sie auf relevant oder nicht relevant vereinfacht wird) zu extrahieren, indem sie die Zeile „Score:“ in der Antwort des Modells identifiziert. Der Chunk wird dann zusammen mit seiner analysierten oder voreingestellten Punktzahl zur bewerteten Liste hinzugefügt. Dieser Teil des Systems fungiert als Retrieval-Evaluator oder Grader.
Die Funktion retrieve_from_vectorstore implementiert eine vectorstore.similarity_search, um die acht relevantesten Dokumentausschnitte basierend auf der Abfrage zu finden, und ruft den page_content aus diesen abgerufenen LangChain-Dokumentobjekten ab.
Dieser Schritt bildet das konzeptionelle Gerüst für das korrigierende RAG-System, sodass sowohl das LLM den Kontext bewertet als auch ermittelt, wie Wissen aus internen und externen Wissensquellen abgerufen werden kann.
Initial retrieval ist die Funktion, die den Vektorspeicher der PDF-Datei durchsucht.
Context scoring nimmt die abgerufenen PDF-Teile und bewertet sie entsprechend ihrer Relevanz.
Fallback to tavily wenn der PDF-Datei nicht genügend relevanter Kontext zur Verfügung steht, wird eine Abfrage an Tavily (Websuche) gesendet.
Source verification ist ein LLM-gestützter Schritt, bei dem überprüft wird, ob die Tavily-Ergebnisse für eine private Richtlinie relevant sind, bevor sie verwendet werden. Diese Funktion verhindert irreführende Antworten aus öffentlichen Gesundheitsprogrammen.
Umformulierung der Suchanfrage und erneute Tavily-Suche: Wenn weiterhin kein passender Kontext gefunden wird, wird die Suchanfrage umformuliert und die Tavily-Suche erneut durchgeführt.
Die endgültige Entscheidung, wenn es einen relevanten Kontext gibt, wird an den LLM mit einer (strengen) Prompt zur Erstellung der Antwort gesendet. Wenn es nach all den brauchbaren Versuchen keinen relevanten Kontext gibt, sendet es eine höfliche Ablehnung.
Im ersten Durchgang des Parameters policy_context_keywords können Sie bestimmte Begriffe aus Ihrer Police (z. B. Name, Versicherer) hinzufügen, um die Suche nach Tavily einzugrenzen.
MIN_CONTEXT_LENGTH definiert die akzeptable Mindestlänge des abgerufenen Kontexts.
SIMIARITY_THRESHOLD definiert die Mindestrelevanzbewertung, die ein Abschnitt haben muss, um als „gut“ zu gelten.
def corrective_rag(...) definiert die Hauptfunktion, die den gesamten RAG-Workflow orchestriert.
Die Funktion corrective_rag beginnt mit der Erstellung von retrieved_context_pieces, um den relevanten Kontext zu erfassen. Zunächst werden chunks_from_vectorstore basierend auf der Abfrage aus dem PDF-Vektorspeicher abgerufen und bewertet. Anschließend bewertet scored_chunks_vector deren Relevanz unter Verwendung des Sprachmodells. Es werden nur good_chunks_vector aufbewahrt, die dem SIMILARITY_THRESHOLD entsprechen. Aus diesen Teilen wird dann der current_context kompiliert.
Wenn der current_context unter MIN_CONTEXT_LENGTH liegt, versucht das System eine Websuche. Es wird eine Tavily_Search-Abfrage erstellt, die möglicherweise Policy_Context_Keywords enthält. Eine direkte Suche (tavily_context_direct) wird durchgeführt. Entscheidend ist, dass ein verification_prompt erstellt und an den LLM gesendet wird, um festzustellen, ob das Websuchergebnis (is_relevant_source) von einer privaten Richtlinie und nicht von einem öffentlichen Programm stammt. Wenn das Resultat YES ist, wird der Kontext hinzugefügt.
Wenn der Kontext weiterhin nicht ausreicht, bereitet sich das System darauf vor, die Abfrage neu zu schreiben. Es verwendet rewrite_prompt, um eine improved_query aus dem LLM abzurufen, und führt dann eine zweite Websuche (tavily_context_rewritten) durch. Auch dieser neue Kontext wird der gleichen Quellenprüfung unterzogen.
Schließlich, wenn len(current_context.strip()) == 0 ist eine letzte Überprüfung. Wenn nach allen Versuchen kein relevanter Kontext gefunden wird, wird eine vordefinierte Ablehnungsmeldung zurückgegeben. Andernfalls wird ein final_prompt mit dem gesamten verifizierten Kontext erstellt und an das Sprachmodell gesendet, um die endgültige Antwort zu generieren.
Die gesamte Funktion corrective_rag behandelt die abgestuften Abruf-, Bewertungs- und Verify-Funktionen von corrective RAG im Detail. Dies ermöglicht eine ständige Aktualisierung der Wissensdatenbank und des Wissensstroms und bietet den Nutzen zuverlässiger und kontextbezogener Antworten.
Führen Sie abschließend die Funktion correktive_rag mit einer Beispielabfrage aus. Es ist wichtig, dass Sie policy_context_keywords angeben, die sich auf Ihr PDF-Dokument beziehen. Diese Schlüsselwörter tragen dazu bei, dass die Tavily-Websuche für Ihre tatsächliche Politik relevanter wird und verhindern, dass allgemeine oder öffentliche Gesundheitsinformationen Ihren Kontext beeinträchtigen.
Bitte beachten Sie die Druckanweisungen zur Kontextlänge und zu den Verifizierungsergebnissen, um den Informationsfluss zu verstehen.
policy_specific_keywords = ["Super Star Health", "Care Health Insurance"] definiert eine Liste von Schlüsselwörtern, die für die hochgeladene Versicherungspolice relevant sind und dabei helfen, die Suchergebnisse im Internet einzugrenzen.
query = "..." proxy = "..." definiert die bestimmte Frage, die ein Benutzer stellen könnte.
result = corrective_rag(query, policy_context_keywords=policy_specific_keywords) ruft die Hauptfunktion corrective_rag auf und übergibt die Anfrage des Benutzers sowie richtlinienspezifische Schlüsselwörter, um den gesamten RAG-Prozess zu starten.
print("\n FINAL ANSWER (...)") zeigt vor dem Drucken der generierten Antwort eine eindeutige Kopfzeile an.
Ausgabe(Ergebnisse) gibt die endgültige Antwort aus, die vom corrective_rag-System zurückgegeben wurde.
Dieser Schritt veranschaulicht, wie das vollständige „corrective RAG“-System mit einer Beispielabfrage und Schlüsselwörtern aufgerufen wird, und demonstriert dessen End-to-End-Funktionalität in einem realistischen Szenario.
Das „corrective RAG“ implementierte eine vollständig koordinierte interne PDF-Wissensdatenbank mit externem Service (Tavily), um umfassende Informationen für komplexe Anfragen abzurufen.
Der abgerufene Kontext wurde mithilfe von LLM-basiertem Scoring und Überprüfung kritischer Quellen genau ausgewertet und gefiltert, um sicherzustellen, dass gültige und zuverlässige Informationen verwendet werden.
Das System hat seine Fähigkeit unter Beweis gestellt, die externe Suche zu verbessern, indem es Suchanfragen von Benutzern intelligent umformuliert, um gezieltere und qualitativ hochwertigere Informationen anzufordern.
Durch die Verwendung der eingeschränkten Generierung wurde in der Regel eine zuverlässige und kontextgenaue Antwort generiert, und das System lehnte es höflich ab, zu antworten, wenn nicht genügend verifizierte Informationen vorlagen.
Dieses Beispiel veranschaulicht, wie LangChain und IBM Granite LLMs auf watsonx zur Entwicklung leistungsstarker und zuverlässiger KI-basierter Anwendungen in sensiblen Bereichen, wie beispielsweise der Beantwortung von Fragen zu Versicherungspolicen, eingesetzt werden können.
Entwickeln, implementieren und verwalten Sie leistungsstarke KI-Assistenten und -Agenten, die Workflows und Prozesse mit generativer KI automatisieren.
Gestalten Sie die Zukunft Ihres Unternehmens mit KI-Lösungen, denen Sie vertrauen können.
Die KI-Services von IBM Consulting unterstützen Sie dabei, die Art und Weise, wie Unternehmen mit KI arbeiten, neu zu denken.