diff --git a/.github/workflows/flux.yml b/.github/workflows/flux.yml new file mode 100644 index 0000000..8bc75be --- /dev/null +++ b/.github/workflows/flux.yml @@ -0,0 +1,69 @@ +name: build-and-push-docker-image + +on: + push: + branches: + - chore/Dockerize-Python + +permissions: + contents: write + +jobs: + build-and-push-docker-image: + runs-on: ubuntu-latest + steps: + + - name: 'Setup yq' + uses: dcarbone/install-yq-action@v1 + + - name: Checkout code + uses: actions/checkout@v2 + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: us-east-1 + + - name: Login to ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 + + - name: Get version + run: | + VERSION=$(cat API/VERSION) + echo "VERSION=${VERSION}" >> $GITHUB_ENV + + - name: Build, Tag, and Push Worker Image to Amazon ECR + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + ECR_REPOSITORY: allora-chatbot-rag-model + IMAGE_BASE_PATH: API + VERSION: ${{ env.VERSION }} + run: | + IMAGE_TAG="${GITHUB_SHA:0:8}" + EXTRA_IMAGE_TAGS="${VERSION};latest" + + # Build and push the image to ECR with the main image tag + docker build --pull -f ${{ env.IMAGE_BASE_PATH }}/Dockerfile -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ${{ env.IMAGE_BASE_PATH }} + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + + # Build and PUSH additional tags + for tag in $(echo $EXTRA_IMAGE_TAGS| tr ";" "\n"); do + docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:$tag + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$tag + done + + # - name: Update Flux Repo + # env: + # VERSION: ${{ env.VERSION }} + # run: | + # git clone https://github.com/allora-network/flux-infra-offchain.git + # cd flux-infra-offchain + # git checkout main + # git pull + # yq -i '.spec.values.containers.chatbot.image.tag="$VERSION"' apps/offchain-testnet/allora-chatbot-rag-model/values.yaml + # git add apps/offchain-testnet/allora-chatbot-api/values.yaml + # git commit -m "Update allora-chatbot-api tag to $VERSION" + # git push diff --git a/components/AiButton.js b/components/AiButton.js new file mode 100644 index 0000000..0d8d1da --- /dev/null +++ b/components/AiButton.js @@ -0,0 +1,43 @@ + +import React, { useState } from "react"; +import ChatComponent from "./chatbutton1"; // Adjust the path as needed + +function AiButton() { + // State to control whether the ChatComponent is displayed + const [showChat, setShowChat] = useState(false); + + // Toggle function to open or close the chat + const toggleChat = () => { + setShowChat((prev) => !prev); + }; + + return ( +
+ {/* Render the "Ask AI" button if the chat is not shown */} + {!showChat && ( + + )} + {/* Render the ChatComponent when showChat is true, passing the onClose prop */} + {showChat && } +
+ ); +} + +export default AiButton; diff --git a/components/chatbutton1.js b/components/chatbutton1.js new file mode 100644 index 0000000..c3f3b35 --- /dev/null +++ b/components/chatbutton1.js @@ -0,0 +1,232 @@ +import React, { useState, useRef, useEffect } from "react"; + +function ChatComponent({ onClose }) { + // holds the current user input and the chat history. + const [inputMessage, setInputMessage] = useState(""); + const [chatHistory, setChatHistory] = useState([]); + const [isLoading, setIsLoading] = useState(false); + + // this references the chat history container. + const chatContainerRef = useRef(null); + + // gives an auto-scroll effect to the bottom whenever the chat history changes. + useEffect(() => { + if (chatContainerRef.current) { + chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight; + } + }, [chatHistory]); + + // this is handler for form submission. + const handleSubmit = async (e) => { + e.preventDefault(); + + // Store the message and immediately clear the input field + const message = inputMessage; + setInputMessage(""); // Clear input immediately + + // Add user's message to the chat history. + const newUserEntry = { sender: "user", text: message }; + setChatHistory((prev) => [...prev, newUserEntry]); + + // Show loading indicator + setIsLoading(true); + + try { + // Send user's message to the FastAPI backend. + const response = await fetch("https://b832b91b8183b88b9c22eda604f1e09.testnet.allora.run/chat", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ message: message }), + }); + console.log("API went through"); + + if (!response.ok) { + throw new Error(`Server error: ${response.statusText}`); + } + + // Parse the JSON response. + const data = await response.json(); + + // Add the assistant's response to the chat history. + const newBotEntry = { + sender: "bot", + text: data.response, + sources: data.sources, + }; + setChatHistory((prev) => [...prev, newBotEntry]); + } catch (error) { + console.error("Error fetching chat response:", error); + // display an error message in the UI. + const errorEntry = { + sender: "bot", text: "Sorry, something went wrong." + }; + setChatHistory((prev) => [...prev, errorEntry]); + } finally { + // Hide loading indicator + setIsLoading(false); + } + }; + + return ( +
+ {/* Header with title and close button */} +
+

Chat with our AI

+ +
+ +
+ {chatHistory.map((entry, index) => ( +
+
+

{entry.text}

+ {entry.sources && entry.sources.length > 0 } +
+
+ ))} + + {/* Loading indicator */} + {isLoading && ( +
+
+
+
+ Thinking... +
+ +
+
+ )} +
+
+ setInputMessage(e.target.value)} + placeholder="Type your message..." + required + style={{ + flex: "1", + padding: "10px", + backgroundColor: "#333", + color: "#fff", + border: "1px solid #555", + borderRadius: "5px", + }} + /> + +
+
+ ); +} + +export default ChatComponent; \ No newline at end of file diff --git a/theme.config.tsx b/theme.config.tsx index 16c46ea..7c6bf10 100644 --- a/theme.config.tsx +++ b/theme.config.tsx @@ -1,6 +1,9 @@ +// theme.config.tsx +import React from 'react' import { useRouter } from 'next/router' -import { DocsThemeConfig, useConfig } from "nextra-theme-docs"; -import React from "react"; +import Link from 'next/link' +import { DocsThemeConfig, useConfig } from 'nextra-theme-docs' +import AiButton from './components/AiButton.js' const config: DocsThemeConfig = { useNextSeoProps() { @@ -16,8 +19,7 @@ const config: DocsThemeConfig = { return ( <> - - + ) @@ -26,7 +28,6 @@ const config: DocsThemeConfig = { head: function useHead() { const { title } = useConfig() const socialCard = '/allora-link-preview' - return ( <> @@ -64,16 +65,25 @@ const config: DocsThemeConfig = { chat: { link: 'https://discord.com/invite/allora' }, + // fixed-position container. footer: { - component: (<>) + component: () => ( +
+ +
+ ), }, sidebar: { autoCollapse: true, }, - // ... other theme options + } export default config; - -// Full theme configs here: https://nextra.site/docs/docs-theme/theme-configuration -