采用代碼聊天:理解代碼庫(kù)的對(duì)話式人工智能 原創(chuàng)
在不斷發(fā)展的軟件開發(fā)環(huán)境中,與代碼庫(kù)進(jìn)行對(duì)話式交互可以改變游戲規(guī)則。
想象一下,有一個(gè)工具可以理解你的代碼,可以回答你的問(wèn)題,提供見(jiàn)解,甚至幫助你調(diào)試問(wèn)題——所有這些都是通過(guò)自然語(yǔ)言查詢實(shí)現(xiàn)的。本文將引導(dǎo)你完成創(chuàng)建對(duì)話式人工智能的過(guò)程,該過(guò)程允許使用Chainlit、Qdrant和OpenAI與你的代碼進(jìn)行對(duì)話。
對(duì)話式人工智能對(duì)代碼庫(kù)的好處
- 簡(jiǎn)化代碼審查:快速審查特定的代碼模塊并了解其場(chǎng)景,而無(wú)需花費(fèi)更多的時(shí)間挖掘文件。
- 高效調(diào)試:詢問(wèn)代碼中潛在的問(wèn)題,并獲得有針對(duì)性的響應(yīng),這有助于減少故障排除所花費(fèi)的時(shí)間。
- 增強(qiáng)學(xué)習(xí): 新的團(tuán)隊(duì)成員可以了解代碼中不同組件的工作原理,而無(wú)需向現(xiàn)有的代碼專家學(xué)習(xí)。
- 改進(jìn)文檔:使用人工智能進(jìn)行總結(jié)有助于生成復(fù)雜代碼的解釋,從而更容易增強(qiáng)文檔。
以下介紹是如何做到這一點(diǎn)的。
為交互準(zhǔn)備代碼庫(kù)
第一步是確保代碼庫(kù)已經(jīng)準(zhǔn)備好進(jìn)行交互。這可以通過(guò)將代碼向量化并將其存儲(chǔ)在向量數(shù)據(jù)庫(kù)中來(lái)實(shí)現(xiàn),從而有效地對(duì)其進(jìn)行審查。
Python
1 import openai
2 import yaml
3 import os
4 import uuid
5 from qdrant_client import QdrantClient, models
6
7 # Load configuration from config.yaml
8 with open("config.yaml", "r") as file:
9 config = yaml.safe_load(file)
10
11 # Extract API keys and URLs from the config
12 qdrant_cloud_url = config["qdrant"]["url"]
13 qdrant_api_key = config["qdrant"]["api_key"]
14 openai_api_key = config["openai"]["api_key"]
15 code_folder_path = config["folder"]["path"]
16
17 # Initialize OpenAI API
18
openai.api_key = openai_api_key
19
20 # Initialize Qdrant client
21 client = QdrantClient(
22 url=qdrant_cloud_url,
23 api_key=qdrant_api_key,
24 )
25
26 def chunk_code(code, chunk_size=512):
27 """
28 Splits the code into chunks, each of a specified size.
29 This helps in generating embeddings for manageable pieces of code.
30 """
31 lines = code.split('\n')
32 for i in range(0, len(lines), chunk_size):
33 yield '\n'.join(lines[i:i + chunk_size])
34
35 def vectorize_and_store_code(code, filename):
36 try:
37 # Chunk the code for better embedding representation
38 code_chunks = list(chunk_code(code))
39
40 # Generate embeddings for each chunk using the OpenAI API
41 embeddings = []
42 for chunk in code_chunks:
43 response = openai.embeddings.create(
44 input=[chunk], # Input should be a list of strings
45 model="text-embedding-ada-002"
46 )
47
48 # Access the embedding data correctly
49 embedding = response.data[0].embedding
50 embeddings.append(embedding)
51
52 # Flatten embeddings if needed or store each chunk as a separate entry
53 if len(embeddings) == 1:
54 final_embeddings = embeddings[0]
55 else:
56 final_embeddings = [item for sublist in embeddings for item in
sublist]
57
58 # Ensure the collection exists
59 try:
60 client.create_collection(
61 collection_name="talk_to_your_code",
62 vectors_config=models.VectorParams(size=len(final_embeddings),
distance=models.Distance.COSINE)
63 )
64 except Exception as e:
65 print("Collection already exists or other error:", e)
66
67 # Insert each chunk into the collection with relevant metadata
68 for i, embedding in enumerate(embeddings):
69 point_id = str(uuid.uuid4())
70 points = [
71 models.PointStruct(
72 id=point_id,
73 vector=embedding,
74 payload={
75 "filename": filename,
76 "chunk_index": i,
77 "total_chunks": len(embeddings),
78 "code_snippet": code_chunks[i]
79 }
80 )
81 ]
82 client.upsert(collection_name="talk_to_your_code", points=points)
83
84 return f"{filename}: Code vectorized and stored successfully."
85
86 except Exception as e:
87 return f"An error occurred with {filename}: {str(e)}"
88
89 def process_files_in_folder(folder_path):
90 for filename in os.listdir(folder_path):
91 if filename.endswith(".py"):
92 file_path = os.path.join(folder_path, filename)
93 with open(file_path, 'r', encoding='utf-8') as file:
94 code = file.read()
95 print(vectorize_and_store_code(code, filename))
96
97 if __name__ == "__main__":
98 process_files_in_folder(code_folder_path)
99
現(xiàn)在了解上述代碼值得注意的方面。
- 加載代碼文件并將其分塊為可管理的部分。
- 分塊是一個(gè)非常重要的環(huán)節(jié)。塊的大小不應(yīng)過(guò)小,以至于你想要了解的函數(shù)或模塊可以在多個(gè)塊中使用;也不應(yīng)該太大,以至于多個(gè)函數(shù)或模塊被壓縮到一個(gè)塊中;這兩種情況都會(huì)降低檢索質(zhì)量。
- 使用OpenAI的text- embeddings -ada-002模型為每個(gè)塊生成嵌入。
- 在Qdrant中處理和存儲(chǔ)嵌入以增強(qiáng)檢索。
- 向代碼塊中添加元數(shù)據(jù)將有助于檢索特定的組件,并使代碼對(duì)話功能更加強(qiáng)大。
- 為簡(jiǎn)單起見(jiàn),使用了一個(gè)文件夾路徑,其中放置了用于構(gòu)建這個(gè)對(duì)話模塊的兩個(gè)代碼文件。這個(gè)設(shè)置可以進(jìn)一步擴(kuò)展,以便指向GitHub上的URL。
- 使用2個(gè)Python文件,即ragwithknowledgegraph.py和ragwithoutknowledgegraph.py用于生成代碼塊的嵌入向量,并將其存儲(chǔ)在矢量數(shù)據(jù)庫(kù)中,可以通過(guò)聊天界面對(duì)其進(jìn)行提問(wèn)。
構(gòu)建對(duì)話界面
現(xiàn)在將設(shè)置一個(gè)Chainlit界面,該界面接受用戶輸入,查詢Qdrant,并返回關(guān)于代碼的場(chǎng)景相關(guān)信息。
Python
1 import chainlit as cl
2 import qdrant_client
3 import openai
4 import yaml
5 from langchain_openai import ChatOpenAI, OpenAIEmbeddings
6 from langchain.prompts import PromptTemplate
7
8 # Load configuration from config.yaml
9 with open("config.yaml", "r") as file:
10 config = yaml.safe_load(file)
11
12 # Extract API keys and URLs from the config
13 qdrant_cloud_url = config["qdrant"]["url"]
14 qdrant_api_key = config["qdrant"]["api_key"]
15 openai_api_key = config["openai"]["api_key"]
16
17 # Initialize OpenAI API
18 openai.api_key = openai_api_key
19
20 # Initialize OpenAI Embeddings
21 embeddings = OpenAIEmbeddings(model="text-embedding-ada-002",
openai_api_key=openai_api_key)
22
23 # Initialize Qdrant client
24 client = qdrant_client.QdrantClient(
25 url=qdrant_cloud_url,
26 api_key=qdrant_api_key,
27 )
28
29 # Initialize OpenAI Chat model
30 chat_model = ChatOpenAI(openai_api_key=openai_api_key, model="gpt-4")
31
32 # Define a simple QA prompt template
33 qa_prompt_template = PromptTemplate(
34 input_variables=["context", "question"],
35 template="Given the following context:\n{context}\nAnswer the following
question:\n{question}"
36 )
37
38 # Chainlit function to handle user input
39 @cl.on_message
40 async def handle_message(message: cl.message.Message):
41 try:
42 # Extract the actual text content from the message object
43 user_input = message.content
44
45 # Generate the query vector using OpenAI Embeddings
46 query_vector = embeddings.embed_query(user_input)
47
48 # Manually send the query to Qdrant
49 response = client.search(
50 collection_name="talk_to_your_code",
51 query_vector=query_vector,
52 limit=5
53 )
54
55 # Process and retrieve the relevant context (code snippets) from the
Qdrant response
56 context_list = []
57 for point in response:
58 code_snippet = point.payload.get('code_snippet', '')
59 filename = point.payload.get('filename', 'Unknown')
60 context_list.append(f"Filename: {filename}\nCode
Snippet:\n{code_snippet}\n")
61
62 context = "\n".join(context_list)
63 if not context:
64 context = "No matching documents found."
65
66 # Generate a response using the LLM with the retrieved context
67 prompt = qa_prompt_template.format(context=context,
question=user_input)
68 response_text = chat_model.predict(prompt)
69
70 # Send the LLM's response
71 await cl.Message(content=response_text).send()
72
73 except Exception as e:
74 # Log the error
75 print(f"Error during message handling: {e}")
76 await cl.Message(content=f"An error occurred: {str(e)}").send()
77
78 if __name__ == "__main__":
79 cl.run()
80
上述代碼的重要方面包括:
- 初始化Chainlit并配置其與OpenAI和Qdrant交互。
- 為輸入生成查詢向量,以幫助從Qdrant檢索相關(guān)代碼片段。
- 定義一個(gè)提示模板,將從Qdrant檢索到的場(chǎng)景與用戶的問(wèn)題結(jié)合起來(lái)。
- 將場(chǎng)景和問(wèn)題提供給OpenAI的語(yǔ)言模型,并將生成的答案返回給用戶。
- 需要注意的是,為了更好地理解,簡(jiǎn)化了一些實(shí)現(xiàn)。
聊天界面的輸出
以下了解當(dāng)要求總結(jié)其中一個(gè)代碼文件時(shí)聊天界面生成的輸出。如上所述,將2個(gè)Python文件加載到vector db,并要求概述其中一個(gè)腳本。
這兩個(gè)腳本中,一個(gè)使用了知識(shí)圖譜來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的RAG(檢索增強(qiáng)生成)用例,而另一個(gè)則沒(méi)有使用。大型語(yǔ)言模型(LLM)以自然語(yǔ)言的方式很好地完成了對(duì)腳本的概述。
下一步驟
- 通過(guò)整合額外的元數(shù)據(jù)來(lái)識(shí)別代碼的各個(gè)方面,從而改進(jìn)檢索。
- 將聊天界面集成到GitHub URL中,并導(dǎo)入可用于提問(wèn)的代碼庫(kù)。
- 通過(guò)詢問(wèn)具體和廣泛的問(wèn)題來(lái)測(cè)試應(yīng)用程序,以了解應(yīng)用程序?qū)?chǎng)景的理解程度。
- 工程師使用各種不同的提示進(jìn)行提示和測(cè)試檢索。
結(jié)論
創(chuàng)建一個(gè)能夠理解你的代碼庫(kù)的對(duì)話式人工智能,將在開發(fā)過(guò)程中解鎖一個(gè)新的效率和洞察力水平。無(wú)論是在簡(jiǎn)化代碼審查、加速調(diào)試,還是增強(qiáng)團(tuán)隊(duì)協(xié)作,這種方法都提供了巨大的價(jià)值。通過(guò)這種簡(jiǎn)單的方法,可以改變與代碼交互的方式。
原文標(biāo)題:Chat With Your Code: Conversational AI That Understands Your Codebase,作者:Prince Bose,Tharakarama Reddy Yernapalli Sreenivasulu,Pavan Vemuri
鏈接:https://dzone.com/articles/conversational-ai-that-understands-your-codebase。
