Spaces:
Sleeping
Sleeping
api v1
Browse files- .gitignore +2 -1
- api/chain.go +89 -0
- api/handler.go +25 -0
- api/models.go +11 -0
- main.go +11 -44
- templates/index.html +40 -0
.gitignore
CHANGED
|
@@ -20,7 +20,8 @@
|
|
| 20 |
# Go workspace file
|
| 21 |
go.work
|
| 22 |
go.work.sum
|
| 23 |
-
|
|
|
|
| 24 |
|
| 25 |
# secrets
|
| 26 |
*.env
|
|
|
|
| 20 |
# Go workspace file
|
| 21 |
go.work
|
| 22 |
go.work.sum
|
| 23 |
+
chats
|
| 24 |
+
system_prompt.txt
|
| 25 |
|
| 26 |
# secrets
|
| 27 |
*.env
|
api/chain.go
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package api
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"context"
|
| 5 |
+
"encoding/json"
|
| 6 |
+
"fmt"
|
| 7 |
+
"log"
|
| 8 |
+
"os"
|
| 9 |
+
"regexp"
|
| 10 |
+
|
| 11 |
+
"github.com/tmc/langchaingo/llms"
|
| 12 |
+
"github.com/tmc/langchaingo/llms/openai"
|
| 13 |
+
)
|
| 14 |
+
|
| 15 |
+
func InvokeChain(apiKey string, userQuery string) (ChatOutput, error) {
|
| 16 |
+
log.Println(userQuery)
|
| 17 |
+
llm, err := openai.New(
|
| 18 |
+
openai.WithModel("llama3-8b-8192"),
|
| 19 |
+
openai.WithBaseURL("https://api.groq.com/openai/v1"),
|
| 20 |
+
openai.WithToken(apiKey),
|
| 21 |
+
)
|
| 22 |
+
if err != nil {
|
| 23 |
+
return ChatOutput{}, fmt.Errorf("error creatnig OpenAI client: %v", err)
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
systemPrompt, err := os.ReadFile("./prompts/system_prompt.txt")
|
| 27 |
+
if err != nil {
|
| 28 |
+
return ChatOutput{}, fmt.Errorf("error reading system prompt file: %v", err)
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
prompt := string(systemPrompt) + "\n\nUser Query: " + userQuery
|
| 32 |
+
|
| 33 |
+
// Write prompt to log file ==> To be removed in production
|
| 34 |
+
err = writePromptToLogFile(prompt)
|
| 35 |
+
if err != nil {
|
| 36 |
+
return ChatOutput{}, fmt.Errorf("error writing prompt to log file: %v", err)
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
ctx := context.Background()
|
| 40 |
+
|
| 41 |
+
var responseContent string
|
| 42 |
+
responseContent, err = llms.GenerateFromSinglePrompt(
|
| 43 |
+
ctx,
|
| 44 |
+
llm,
|
| 45 |
+
prompt,
|
| 46 |
+
llms.WithTemperature(0.8),
|
| 47 |
+
llms.WithJSONMode(),
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
if err != nil {
|
| 51 |
+
return ChatOutput{}, fmt.Errorf("error in generating content: %v", err)
|
| 52 |
+
}
|
| 53 |
+
log.Printf("Raw response: %s", responseContent)
|
| 54 |
+
|
| 55 |
+
responseContent = extractResponse(responseContent)
|
| 56 |
+
|
| 57 |
+
var chatOutput ChatOutput
|
| 58 |
+
if err := json.Unmarshal([]byte(responseContent), &chatOutput); err != nil {
|
| 59 |
+
return ChatOutput{}, fmt.Errorf("error unmarshalling response: %v", err)
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
return chatOutput, nil
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
func extractResponse(responseContent string) string {
|
| 66 |
+
re := regexp.MustCompile("```(.*?)```")
|
| 67 |
+
matches := re.FindStringSubmatch(responseContent)
|
| 68 |
+
if len(matches) > 1 {
|
| 69 |
+
return matches[1]
|
| 70 |
+
}
|
| 71 |
+
return responseContent
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
func writePromptToLogFile(prompt string) error {
|
| 75 |
+
if _, err := os.Stat("./log"); os.IsNotExist(err) {
|
| 76 |
+
os.Mkdir("./log", 0755)
|
| 77 |
+
}
|
| 78 |
+
file, err := os.OpenFile("./log/prompt.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
| 79 |
+
if err != nil {
|
| 80 |
+
return fmt.Errorf("error opening log file: %v", err)
|
| 81 |
+
}
|
| 82 |
+
defer file.Close()
|
| 83 |
+
|
| 84 |
+
if _, err := file.WriteString(prompt); err != nil {
|
| 85 |
+
return fmt.Errorf("error writing to log file: %v", err)
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
return nil
|
| 89 |
+
}
|
api/handler.go
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package api
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"net/http"
|
| 5 |
+
"os"
|
| 6 |
+
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func ChatHandler(c *gin.Context) {
|
| 11 |
+
var inputData ChatInput
|
| 12 |
+
if err := c.ShouldBindJSON(&inputData); err != nil {
|
| 13 |
+
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
| 14 |
+
return
|
| 15 |
+
}
|
| 16 |
+
apiKey := os.Getenv("GROQ_API_KEY")
|
| 17 |
+
response, err := InvokeChain(apiKey, inputData.UserQuery)
|
| 18 |
+
if err != nil {
|
| 19 |
+
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
| 20 |
+
return
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
// response := "Hello, World!"
|
| 24 |
+
c.JSON(http.StatusOK, response)
|
| 25 |
+
}
|
api/models.go
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package api
|
| 2 |
+
|
| 3 |
+
type ChatInput struct {
|
| 4 |
+
UserQuery string `json:"user_query" binding:"required"`
|
| 5 |
+
}
|
| 6 |
+
|
| 7 |
+
type ChatOutput struct {
|
| 8 |
+
Score int `json:"score" binding:"required"`
|
| 9 |
+
Description string `json:"description" binding:"required"`
|
| 10 |
+
Messages []map[string]interface{} `json:"messages" binding:"required"`
|
| 11 |
+
}
|
main.go
CHANGED
|
@@ -1,56 +1,23 @@
|
|
| 1 |
package main
|
| 2 |
|
| 3 |
import (
|
| 4 |
-
"
|
| 5 |
-
"fmt"
|
| 6 |
-
"os"
|
| 7 |
|
| 8 |
-
"
|
| 9 |
-
|
| 10 |
-
"github.com/
|
| 11 |
)
|
| 12 |
|
| 13 |
func main() {
|
| 14 |
-
|
| 15 |
-
if err != nil {
|
| 16 |
-
fmt.Fprintln(os.Stderr, err)
|
| 17 |
-
os.Exit(1)
|
| 18 |
-
}
|
| 19 |
-
fmt.Println(content)
|
| 20 |
-
}
|
| 21 |
-
|
| 22 |
-
func run() (string, error) {
|
| 23 |
-
err := godotenv.Load()
|
| 24 |
-
if err != nil {
|
| 25 |
-
return "", fmt.Errorf("error loading .env file: %v", err)
|
| 26 |
-
}
|
| 27 |
-
|
| 28 |
-
apiKey := os.Getenv("OPENAI_API_KEY")
|
| 29 |
-
if apiKey == "" {
|
| 30 |
-
return "", fmt.Errorf("OPENAI_API_KEY not set in .env file")
|
| 31 |
-
}
|
| 32 |
-
|
| 33 |
-
llm, err := openai.New()
|
| 34 |
-
if err != nil {
|
| 35 |
-
return "", fmt.Errorf("error creating OpenAI client: %v", err)
|
| 36 |
-
}
|
| 37 |
-
|
| 38 |
-
fmt.Println("OpenAI client created successfully")
|
| 39 |
-
|
| 40 |
-
ctx := context.Background()
|
| 41 |
-
prompt := "What is GoLang?"
|
| 42 |
|
| 43 |
-
|
| 44 |
-
ctx,
|
| 45 |
-
llm,
|
| 46 |
-
prompt,
|
| 47 |
-
)
|
| 48 |
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
}
|
| 52 |
|
| 53 |
-
|
| 54 |
|
| 55 |
-
|
| 56 |
}
|
|
|
|
| 1 |
package main
|
| 2 |
|
| 3 |
import (
|
| 4 |
+
"net/http"
|
|
|
|
|
|
|
| 5 |
|
| 6 |
+
"golang-chain/api"
|
| 7 |
+
|
| 8 |
+
"github.com/gin-gonic/gin"
|
| 9 |
)
|
| 10 |
|
| 11 |
func main() {
|
| 12 |
+
r := gin.Default()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
+
r.LoadHTMLGlob("templates/*")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
|
| 16 |
+
r.GET("/", func(c *gin.Context) {
|
| 17 |
+
c.HTML(http.StatusOK, "index.html", nil)
|
| 18 |
+
})
|
| 19 |
|
| 20 |
+
r.POST("/chat/", api.ChatHandler)
|
| 21 |
|
| 22 |
+
r.Run(":8080")
|
| 23 |
}
|
templates/index.html
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Chat Interface</title>
|
| 7 |
+
</head>
|
| 8 |
+
<body>
|
| 9 |
+
<h1>Chat with the AI</h1>
|
| 10 |
+
<form id="chatForm">
|
| 11 |
+
<label for="userQuery">Enter your query:</label>
|
| 12 |
+
<input type="text" id="userQuery" name="user_query" required>
|
| 13 |
+
<button type="submit">Submit</button>
|
| 14 |
+
</form>
|
| 15 |
+
<h2>Response</h2>
|
| 16 |
+
<div id="response"></div>
|
| 17 |
+
|
| 18 |
+
<script>
|
| 19 |
+
document.getElementById('chatForm').addEventListener('submit', async (event) => {
|
| 20 |
+
event.preventDefault();
|
| 21 |
+
const formData = new FormData(event.target);
|
| 22 |
+
const responseDiv = document.getElementById('response');
|
| 23 |
+
responseDiv.innerHTML = 'Loading...';
|
| 24 |
+
|
| 25 |
+
const response = await fetch('/chat/', {
|
| 26 |
+
method: 'POST',
|
| 27 |
+
body: JSON.stringify({
|
| 28 |
+
user_query: formData.get('user_query')
|
| 29 |
+
}),
|
| 30 |
+
headers: {
|
| 31 |
+
'Content-Type': 'application/json'
|
| 32 |
+
}
|
| 33 |
+
});
|
| 34 |
+
|
| 35 |
+
const result = await response.json();
|
| 36 |
+
responseDiv.innerHTML = JSON.stringify(result, null, 2);
|
| 37 |
+
});
|
| 38 |
+
</script>
|
| 39 |
+
</body>
|
| 40 |
+
</html>
|