Your resource for web content, online publishing
and the distribution of digital products.
S M T W T F S
1
 
2
 
3
 
4
 
5
 
6
 
7
 
8
 
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
 
28
 
29
 
30
 
 
 
 
 
 

How to Turn Your OpenAPI Specification Into an AI Chatbot With RAG

DATE POSTED:September 24, 2024

Причина по которая я захотел поделиться своим опытом простая. В каждой средней компании есть много микросервисов и различных АПИ. Команды пилять микросервисы. Каждая команда взаимодействует друг с другом. Спасибо большое Фастапи и ее создателю за то что сделали прекрасынй фрейморк на основе пайдентика генерирующий все необходимые спеки. Но проблема все еще актуальна, некоторым стартапам не хватает времени писать нормальную документацию - дак может и не надо, если часть кода уже генерируется.

\

  1. Что я использовал
  • Стримлит
  • Хрома
  • Лангчен
  • Оламма

\ Я решил попробовать провести эксперимент и соединить Swagger и с OpenAI и посмотреть что из этого получиться. Это статья туториал / гайд для тех кто хочет узнать чем все кончилось и как я это сделал на основе RAG with ChromaDB and Langchain.

\ Цель

Fast to find. Information and ask about something “How to create item with API?“

\ Все шаги в RAG делятся на 3 части

  1. Взять информацию, разбить ее на чанки и положить в векторное хранилище.
  2. Достать во время запроса от клиента и отправить в модель
  3. Сравнить результат и ожидание

\

Пишем сплиттер

для того чтобы написать сплиттер обычно лангчейн предоставляет много заготовленных штук, но так как в нашем случае спецификация это список запросов которые связаны с моделями лучше всего взять и разбить это на просто запросы. Для этого я написал простой снипет. Это максимально простая функция кторая разделяет всю полученную спеку на простые части. И добавляет связанные модели к патчу.

def get_openapi_spec_paths(specification: dict) -> dict: paths = [] for p in specification["paths"]: for m in specification["paths"][p]: path = specification["paths"][p][m] path["method"] = m path["path"] = p paths.append(path) return paths Загрузка документов

После того как мы разделили на чанки нам нужно их заэнкодировать в векторное предстовление и загрузить в хрома дб. В дальнейшем перед тем как делать запрос в чат гпт мы сделаем векторный поиск по эмбедингам чтобы достать релевантные документы.

\

import json from langchain.docstore.document import Document from langchain_openai import OpenAIEmbeddings from langchain_chroma import Chroma specification = get_openapi_spec(url) paths = get_openapi_spec_paths(specification) dumped_paths = dump_openapi_spec_to_chroma_docs(paths) # Dump documents to Chroma documents for p in paths: dumped_paths.append( Document(page_content=json.dumps(p), metadata={"source": "local"}) ) # Init embeddings model embeddings = OpenAIEmbeddings( model="text-embedding-ada-002" ) # Upload to database Chroma.from_documents( documents=dumped_paths, embedding=embeddings, persist_directory="data", collection_name="spec", )

\ В этом примере, мы сохраняем данные локально в директорию ‘data’, но Chroma может работать как и в короткой памяти так и как отдельный инстанс.

Пишем ретривер и чейн

Мы готовы к тому чтобы сделать первый запрос. Я загрузил пример простого API про собачек, который написал на фастапи и добавил ссылку в скрипт.

\ В качестве модели мы будем использовать chatgpt-4o

embeddings = OpenAIEmbeddings(model=settings.OPENAI_API_EMBEDDINGS_MODEL) llm = ChatOpenAI(api_key=settings.OPENAI_API_KEY, model=settings.OPEN_API_MODEL) chroma_db = Chroma( persist_directory="data", embedding_function=embeddings, collection_name="spec", ) retriever = chroma_db.as_retriever() prompt = PromptTemplate.from_template( """ System: You are an assistant that converts OpenAPI JSON specs into neatly structured, human-readable text with summary, description, tags, produces, responses, parameters, method, and curl examples. EXAMPLE ANSWER: ### GET /dogs **Summary**: Retrieve a list of dogs **Description**: Get a filtered list of dogs based on query parameters such as breed, age, or size. **Tags**: Dogs **Produces**: application/json **Parameters**: - **Query**: - `breed` (string, optional): Filter by dog breed. - `age` (integer, optional): Filter by dog age. - `size` (string, optional): Filter by dog size (small, medium, large). **Method**: GET **Curl Example**: ```sh curl -X GET "https://api.example.com/dogs?breed=labrador&size=medium" -H "Authorization: Bearer " ``` Now, format the following OpenAPI spec: {context} {question} """ ) def format_docs(docs): return "\n\n".join(doc.page_content for doc in docs) chain = ( {"context": retriever | format_docs, "question": RunnablePassthrough()} | prompt | llm | StrOutputParser() ) chain.invoke(("How to get list of dogs?")

\ Я докуртил few shot промп и финальную версию можно увидеть в гитхаб репозитори.

Пример на основе Lamma

Если вы не готовы использовать OpenAPI в целях например безопасности или по другим причнам, всегда есть возможность запустить на Lamma7B для этого установить себе ламу. Спульте и заменить llm на

\

# pull model before usage # ollama pull llama3.1 from langchain_ollama import OllamaLLM llm = OllamaLLM(model="llama3.1:8b") Lets Add StreamLete

куда же без этого молодца? В наших экспериментах? Даа.

\

import streamlit as st if "messages" not in st.session_state: st.session_state.messages = [] for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("Enter your message."): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) with st.chat_message("assistant"): if (len(st.session_state.messages)): r = chat_with_model(st.session_state.messages[-1]["content"]) response = st.write(r) st.session_state.messages.append({"role": "assistant", "content": response})

\ Пару строк и получаем что то что мы уже можем трогать.

\

Результаты и тестовая спека

В рещультате я проетстировал

\ Резудльтаты впечатляют, все зависит от модели. А теперь подумайте сколько времени сэкономит это компаниям?

Заключение

Если вы нашли эту статью и эксперимент полезной для себя, поставьте звезду на гитхаб! RAG помог мне сохранить время и силы разобраться в разных спеках различных команд. В любом случае чем понятнее контекст и так далее тем улчше. Поэтому пишите качесвенно докстринги и документацию Фастапи и пайдентик в этом помогут.

\ Ссылка на гитхабыч чтобы запустить проект локльно (не забудь нажать на звездочку)