From 6d9686e3731e0fa17fdcc3fe42a34c5bee6406e9 Mon Sep 17 00:00:00 2001 From: Anibal Angulo Date: Tue, 25 Nov 2025 07:05:14 +0000 Subject: [PATCH] add healthcheck to remaining apps --- .github/workflows/release.yml | 43 +---- apps/Test/.eslintrc.cjs | 18 -- apps/Test/gui/App.tsx | 65 ------- apps/Test/gui/assets/banortelogo.png | Bin 10785 -> 0 bytes apps/Test/gui/assets/brujula.png | Bin 13646 -> 0 bytes apps/Test/gui/assets/brujula_elipse.png | Bin 30751 -> 0 bytes .../gui/assets/chat_maya_boton_enviar.png | Bin 5781 -> 0 bytes .../gui/assets/chat_maya_default_avatar.png | Bin 6183 -> 0 bytes apps/Test/gui/assets/sidebar_maya_contigo.png | Bin 99097 -> 0 bytes apps/Test/gui/index.css | 16 -- apps/Test/gui/main.tsx | 5 - apps/Test/gui/store/conversationStore.ts | 19 -- apps/Test/gui/store/messageStore.ts | 14 -- apps/Test/gui/utils/request.ts | 16 -- apps/Test/gui/vite-env.d.ts | 1 - apps/Test/index.html | 13 -- apps/Test/package.json | 40 ----- apps/Test/postcss.config.js | 6 - apps/Test/pyproject.toml | 18 -- apps/Test/tailwind.config.js | 27 --- apps/Test/tsconfig.json | 25 --- apps/Test/tsconfig.node.json | 11 -- apps/Test/vite.config.ts | 17 -- apps/bursatil/.k8s/deployment.yaml | 42 +++++ apps/bursatil/.k8s/ingress.yaml | 19 ++ apps/bursatil/.k8s/secrets.yaml | 17 ++ apps/bursatil/.k8s/service.yaml | 14 ++ apps/{ChatEgresos => egresos}/.eslintrc.cjs | 0 apps/egresos/.k8s/deployment.yaml | 42 +++++ apps/egresos/.k8s/ingress.yaml | 19 ++ apps/egresos/.k8s/secrets.yaml | 17 ++ apps/egresos/.k8s/service.yaml | 14 ++ apps/{ChatEgresos => egresos}/api/__init__.py | 0 .../api/agent/__init__.py | 0 .../api/agent/main.py | 0 .../api/agent/system_prompt.md | 0 apps/{ChatEgresos => egresos}/api/config.py | 0 apps/{ChatEgresos => egresos}/api/context.py | 0 apps/{ChatEgresos => egresos}/api/server.py | 66 +++---- .../api/services/__init__.py | 0 .../api/services/stream_response.py | 0 apps/{ChatEgresos => egresos}/gui/App.tsx | 0 .../gui/assets/banortelogo.png | Bin .../gui/assets/brujula.png | Bin .../gui/assets/brujula_elipse.png | Bin .../gui/assets/chat_maya_boton_enviar.png | Bin .../gui/assets/chat_maya_default_avatar.png | Bin .../gui/assets/sidebar_maya_contigo.png | Bin apps/{ChatEgresos => egresos}/gui/index.css | 0 apps/{ChatEgresos => egresos}/gui/main.tsx | 0 .../gui/store/conversationStore.ts | 0 .../gui/store/messageStore.ts | 0 .../gui/utils/request.ts | 0 .../gui/vite-env.d.ts | 0 apps/{ChatEgresos => egresos}/index.html | 0 apps/{ChatEgresos => egresos}/package.json | 0 .../postcss.config.js | 0 apps/{ChatEgresos => egresos}/pyproject.toml | 2 +- apps/{ChatEgresos => egresos}/readme.md | 0 .../tailwind.config.js | 0 apps/{ChatEgresos => egresos}/tsconfig.json | 0 .../tsconfig.node.json | 0 apps/{ChatEgresos => egresos}/vite.config.ts | 0 apps/normativa/.k8s/deployment.yaml | 42 +++++ apps/normativa/.k8s/ingress.yaml | 19 ++ apps/normativa/.k8s/secrets.yaml | 17 ++ apps/normativa/.k8s/service.yaml | 14 ++ apps/normativa/api/server.py | 164 +++++++++--------- apps/pyme/.k8s/deployment.yaml | 42 +++++ apps/pyme/.k8s/ingress.yaml | 19 ++ apps/pyme/.k8s/secrets.yaml | 17 ++ apps/pyme/.k8s/service.yaml | 14 ++ apps/pyme/api/server.py | 162 +++++++++-------- apps/riesgos/.k8s/deployment.yaml | 42 +++++ apps/riesgos/.k8s/ingress.yaml | 19 ++ apps/riesgos/.k8s/secrets.yaml | 17 ++ apps/riesgos/.k8s/service.yaml | 14 ++ apps/riesgos/api/server/__init__.py | 6 + apps/voz-del-cliente/.k8s/deployment.yaml | 42 +++++ apps/voz-del-cliente/.k8s/ingress.yaml | 19 ++ apps/voz-del-cliente/.k8s/secrets.yaml | 17 ++ apps/voz-del-cliente/.k8s/service.yaml | 14 ++ apps/voz-del-cliente/api/config.py | 6 +- apps/voz-del-cliente/api/server.py | 12 +- compose.yaml | 46 +---- scripts/replace-app-name.sh | 30 ++++ uv.lock | 82 +++------ 87 files changed, 850 insertions(+), 632 deletions(-) delete mode 100644 apps/Test/.eslintrc.cjs delete mode 100644 apps/Test/gui/App.tsx delete mode 100644 apps/Test/gui/assets/banortelogo.png delete mode 100644 apps/Test/gui/assets/brujula.png delete mode 100644 apps/Test/gui/assets/brujula_elipse.png delete mode 100644 apps/Test/gui/assets/chat_maya_boton_enviar.png delete mode 100644 apps/Test/gui/assets/chat_maya_default_avatar.png delete mode 100644 apps/Test/gui/assets/sidebar_maya_contigo.png delete mode 100644 apps/Test/gui/index.css delete mode 100644 apps/Test/gui/main.tsx delete mode 100644 apps/Test/gui/store/conversationStore.ts delete mode 100644 apps/Test/gui/store/messageStore.ts delete mode 100644 apps/Test/gui/utils/request.ts delete mode 100644 apps/Test/gui/vite-env.d.ts delete mode 100644 apps/Test/index.html delete mode 100644 apps/Test/package.json delete mode 100644 apps/Test/postcss.config.js delete mode 100644 apps/Test/pyproject.toml delete mode 100644 apps/Test/tailwind.config.js delete mode 100644 apps/Test/tsconfig.json delete mode 100644 apps/Test/tsconfig.node.json delete mode 100644 apps/Test/vite.config.ts create mode 100644 apps/bursatil/.k8s/deployment.yaml create mode 100644 apps/bursatil/.k8s/ingress.yaml create mode 100644 apps/bursatil/.k8s/secrets.yaml create mode 100644 apps/bursatil/.k8s/service.yaml rename apps/{ChatEgresos => egresos}/.eslintrc.cjs (100%) create mode 100644 apps/egresos/.k8s/deployment.yaml create mode 100644 apps/egresos/.k8s/ingress.yaml create mode 100644 apps/egresos/.k8s/secrets.yaml create mode 100644 apps/egresos/.k8s/service.yaml rename apps/{ChatEgresos => egresos}/api/__init__.py (100%) rename apps/{ChatEgresos => egresos}/api/agent/__init__.py (100%) rename apps/{ChatEgresos => egresos}/api/agent/main.py (100%) rename apps/{ChatEgresos => egresos}/api/agent/system_prompt.md (100%) rename apps/{ChatEgresos => egresos}/api/config.py (100%) rename apps/{ChatEgresos => egresos}/api/context.py (100%) rename apps/{ChatEgresos => egresos}/api/server.py (74%) rename apps/{ChatEgresos => egresos}/api/services/__init__.py (100%) rename apps/{ChatEgresos => egresos}/api/services/stream_response.py (100%) rename apps/{ChatEgresos => egresos}/gui/App.tsx (100%) rename apps/{ChatEgresos => egresos}/gui/assets/banortelogo.png (100%) rename apps/{ChatEgresos => egresos}/gui/assets/brujula.png (100%) rename apps/{ChatEgresos => egresos}/gui/assets/brujula_elipse.png (100%) rename apps/{ChatEgresos => egresos}/gui/assets/chat_maya_boton_enviar.png (100%) rename apps/{ChatEgresos => egresos}/gui/assets/chat_maya_default_avatar.png (100%) rename apps/{ChatEgresos => egresos}/gui/assets/sidebar_maya_contigo.png (100%) rename apps/{ChatEgresos => egresos}/gui/index.css (100%) rename apps/{ChatEgresos => egresos}/gui/main.tsx (100%) rename apps/{ChatEgresos => egresos}/gui/store/conversationStore.ts (100%) rename apps/{ChatEgresos => egresos}/gui/store/messageStore.ts (100%) rename apps/{ChatEgresos => egresos}/gui/utils/request.ts (100%) rename apps/{ChatEgresos => egresos}/gui/vite-env.d.ts (100%) rename apps/{ChatEgresos => egresos}/index.html (100%) rename apps/{ChatEgresos => egresos}/package.json (100%) rename apps/{ChatEgresos => egresos}/postcss.config.js (100%) rename apps/{ChatEgresos => egresos}/pyproject.toml (95%) rename apps/{ChatEgresos => egresos}/readme.md (100%) rename apps/{ChatEgresos => egresos}/tailwind.config.js (100%) rename apps/{ChatEgresos => egresos}/tsconfig.json (100%) rename apps/{ChatEgresos => egresos}/tsconfig.node.json (100%) rename apps/{ChatEgresos => egresos}/vite.config.ts (100%) create mode 100644 apps/normativa/.k8s/deployment.yaml create mode 100644 apps/normativa/.k8s/ingress.yaml create mode 100644 apps/normativa/.k8s/secrets.yaml create mode 100644 apps/normativa/.k8s/service.yaml create mode 100644 apps/pyme/.k8s/deployment.yaml create mode 100644 apps/pyme/.k8s/ingress.yaml create mode 100644 apps/pyme/.k8s/secrets.yaml create mode 100644 apps/pyme/.k8s/service.yaml create mode 100644 apps/riesgos/.k8s/deployment.yaml create mode 100644 apps/riesgos/.k8s/ingress.yaml create mode 100644 apps/riesgos/.k8s/secrets.yaml create mode 100644 apps/riesgos/.k8s/service.yaml create mode 100644 apps/voz-del-cliente/.k8s/deployment.yaml create mode 100644 apps/voz-del-cliente/.k8s/ingress.yaml create mode 100644 apps/voz-del-cliente/.k8s/secrets.yaml create mode 100644 apps/voz-del-cliente/.k8s/service.yaml create mode 100755 scripts/replace-app-name.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e7d218c..1a30a46 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,13 +20,12 @@ jobs: runs-on: ubuntu-latest outputs: bursatil: ${{ steps.filter.outputs.bursatil }} - ChatEgresos: ${{ steps.filter.outputs.ChatEgresos }} + egresos: ${{ steps.filter.outputs.egresos }} inversionistas: ${{ steps.filter.outputs.inversionistas }} normativa: ${{ steps.filter.outputs.normativa }} ocp: ${{ steps.filter.outputs.ocp }} pyme: ${{ steps.filter.outputs.pyme }} riesgos: ${{ steps.filter.outputs.riesgos }} - Test: ${{ steps.filter.outputs.Test }} voz-del-cliente: ${{ steps.filter.outputs.voz-del-cliente }} steps: - uses: actions/checkout@v4 @@ -39,8 +38,8 @@ jobs: filters: | bursatil: - 'apps/bursatil/**' - ChatEgresos: - - 'apps/ChatEgresos/**' + egresos: + - 'apps/egresos/**' inversionistas: - 'apps/inversionistas/**' normativa: @@ -51,8 +50,6 @@ jobs: - 'apps/pyme/**' riesgos: - 'apps/riesgos/**' - Test: - - 'apps/Test/**' voz-del-cliente: - 'apps/voz-del-cliente/**' @@ -80,9 +77,9 @@ jobs: build-args: | PACKAGE=bursatil - build-ChatEgresos: + build-egresos: needs: detect-changes - if: needs.detect-changes.outputs.ChatEgresos == 'true' + if: needs.detect-changes.outputs.egresos == 'true' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -99,10 +96,10 @@ jobs: file: .containers/python/Dockerfile push: true tags: | - ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}-ChatEgresos:latest - ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}-ChatEgresos:${{ github.sha }} + ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}-egresos:latest + ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}-egresos:${{ github.sha }} build-args: | - PACKAGE=ChatEgresos + PACKAGE=egresos build-inversionistas: needs: detect-changes @@ -224,30 +221,6 @@ jobs: build-args: | PACKAGE=riesgos - build-Test: - needs: detect-changes - if: needs.detect-changes.outputs.Test == 'true' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Log in to Gitea Registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ secrets.REGISTRY_USERNAME }} - password: ${{ secrets.REGISTRY_PASSWORD }} - - name: Build and push - uses: docker/build-push-action@v5 - with: - context: . - file: .containers/python/Dockerfile - push: true - tags: | - ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}-Test:latest - ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}-Test:${{ github.sha }} - build-args: | - PACKAGE=Test - build-voz-del-cliente: needs: detect-changes if: needs.detect-changes.outputs.voz-del-cliente == 'true' diff --git a/apps/Test/.eslintrc.cjs b/apps/Test/.eslintrc.cjs deleted file mode 100644 index d6c9537..0000000 --- a/apps/Test/.eslintrc.cjs +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - root: true, - env: { browser: true, es2020: true }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react-hooks/recommended', - ], - ignorePatterns: ['dist', '.eslintrc.cjs'], - parser: '@typescript-eslint/parser', - plugins: ['react-refresh'], - rules: { - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], - }, -} diff --git a/apps/Test/gui/App.tsx b/apps/Test/gui/App.tsx deleted file mode 100644 index caf827a..0000000 --- a/apps/Test/gui/App.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { Chat, ChatSidebar } from "@banorte/chat-ui"; -import { messageStore } from "./store/messageStore"; -import { conversationStore } from "./store/conversationStore"; -import { httpRequest } from "./utils/request"; - -// Assets -import banorteLogo from "./assets/banortelogo.png"; -import sidebarMaya from "./assets/sidebar_maya_contigo.png"; -import brujulaElipse from "./assets/brujula_elipse.png"; -import sendIcon from "./assets/chat_maya_boton_enviar.png"; -import userAvatar from "./assets/chat_maya_default_avatar.png"; -import botAvatar from "./assets/brujula.png"; - -function App() { - const { messages, pushMessage } = messageStore(); - const { - conversationId, - setConversationId, - setAssistantName, - receivingMsg, - setReceivingMsg - } = conversationStore(); - - const handleStartConversation = async (user: string, assistant: string): Promise => { - const response = await httpRequest("POST", "/v1/conversation", { user, assistant }); - console.log("Conversation id:", response.conversation_id); - return response.conversation_id; - }; - - const handleFeedback = async (key: string, rating: string): Promise => { - await httpRequest("POST", "/v1/feedback", { key, rating }); - }; - - const assistant = "Maya" + "Test"; - - return ( -
-
- - -
-
- ); -} - -export default App; diff --git a/apps/Test/gui/assets/banortelogo.png b/apps/Test/gui/assets/banortelogo.png deleted file mode 100644 index 86bbe950b1282395d6f9f6f54bf672f38b412b9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10785 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 Ws_^qo3{lZZ@>I)Ev-XKY^#1`IzLu~6 diff --git a/apps/Test/gui/assets/brujula.png b/apps/Test/gui/assets/brujula.png deleted file mode 100644 index 9d9bf0705211c8ca22f69dca9678022464e71e67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13646 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 F{SP(amzn?o diff --git a/apps/Test/gui/assets/brujula_elipse.png b/apps/Test/gui/assets/brujula_elipse.png deleted file mode 100644 index 0b57cebeaf072b4d4a035e90e352ea38d17b5b4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30751 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 diff --git a/apps/Test/gui/assets/chat_maya_default_avatar.png b/apps/Test/gui/assets/chat_maya_default_avatar.png deleted file mode 100644 index ed9da7f7e4ee36682d2cb23fe999ad61c62ccd17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6183 zcmcIo2|U#6*B?Yg_M(t!$Wq2Ej4{^A5;FD>Dzh>*TQhdDBx_2FLY7T;^=XqwLtSk;~-Li8F2n5<{YGP;u zyffCHygb0`>!vhU5Qqa!F)*+?KxE)aV4Fh+!Ab}WMpGFCQi@B6tubq`5|5~nGHSYE z&-;3qsc3CQeO?!1>KqMr%s04v+teTdFG{}?^jY{KUB+eL45#9ux&w230bEUap$6v! zxX%xLOdY~VKjFy0_oRkfhc7thdv(R#8Exy8ASZGLTO?+A<$HpJ6;C%x4$bfe_h2ih z)gP?{A!W18xa3?brAWIYw>+)s%;Q09di-1ZNnxSjJc~Y*u;u=|Yb#P#TUcK~X03|> z!Y6`z*}AeZm|6kW2@Z3aW2b_hE(>-aov~}XMLOC!t#Cj-c5~9jCu$Y45m9Dh&!1UK zw9Ih1B4nv(nF{;Tf~v)!HC>UO1rj~|5bu5!U5TRyd~T=)9g)<&GJ$Vq?hu^8`PmUG z(adrV{&J%-r?C0$I)Xu<+DDeF3%2?#0F!)7lcQ`9h+k~|$pK1EkpzKwuTbn9Jsh#- zS_B476}Qf>st=6`Sc5=1`aVn?;S|XOj3>EK=(>=Z${GlmLezygps;W((}3hoG4W%O zZ2c_k2!5vs7$QVp53J*(1vsFQJaAwi8kNr0^3jES^Q#41uiu72z~4+fPU%9v7t|4J z1vX%?NMMwz29$tMM}g58RfL9`ItHTxM#2%AFt{cRp$0{0XsN@skVx>42Ly=5B9gUi z42^%p0zTTmx3{Xdnks|k1_Q)`fx(e5BoYc(K-s=@51bE_&X)V>!H~oz zuqaFq3WE+__lUzYJUw(F0MhR%(3l%;>Fggg0ffPPa7-9N6~3O*H$x&}!;b06qJ9fb zB)~{i5{*RnU<0;@4O@UEEOx{EZ{5;p8`f+OBQF5akKF#&nr-LHB*AP*Y=$R`Kr-?I zBFg;)#`drw{YlL~SPqzPEM~ehJQ!?u#xF?N_=+E{&njE}^a3_8 zSg$GutmHtU6B*uY<#m)l){qQw9wc1|5{^`d!Zo1?q#XjO1=rAmBcSWA@b9KrKu1KJ z2ksZf>T3VVm_ekFegCZ~k)TCpuxL1dWeN@FMuIWvZr`F|v0A2dwg-+*AekEKLI9|$ z6bey`j3<-S32JbtCJ{k|;^06~93F{)uBV2=Ya&T%Ktrr22CO$^5Iolvu)h9#GY}aB zz{du4T0}U8j8}&fp=dl_9jb;_CqnTUO%fDOz$4WNXic;RQsbvLOBMy_M;!I9Ue{3( z*HK|K$v8EX8kD4_L4ayt)JagB8W|47X`sk(90IKgAcKJajBCK4GFVs!5#U^Hy&Jyc zHKDM9>iPcYFI&>-A6HZg_?r;5aD??<(S;D!>r4Xj{C=DAcRc+gMBmqYyORK?|DyQc z&DadGhc}KzI^YIy`cL!)`xSmR&g);JN8u0%90s5gjwTVIK*e!TO-(!!s)^ zPJ@j4nf))&|Eb3RA^IQW65MfgHxe*@VUSGjv2`J27J~-H zF_}~f0k>X0m=~S+W0-9S0_?#6|0(}p#vzhel)o_d*C-nh!2gHw{%xK9SvUSmmHj`} z3AVnWd~YGxf9N3=*UI{?SQPo{C`9F6J?BYRAh|b7WFB{aE>FgHeHy zVME%^UP5zbwpUVeYqsFi7W8HlBh{07bMpXXogpWLJ)KpeZPQpl4R3c^?S(khSJleg2$6Uy z?_y&ks_ivdWT+Võ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�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 Lf0n9}FbVlTzU5Z{ diff --git a/apps/Test/gui/index.css b/apps/Test/gui/index.css deleted file mode 100644 index 903f821..0000000 --- a/apps/Test/gui/index.css +++ /dev/null @@ -1,16 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -.markdown a { - color: #0000FF; - text-decoration: underline; -} - -.markdown a:hover { - color: #FF0000; -} - -.markdown a:visited { - color: #800080; -} \ No newline at end of file diff --git a/apps/Test/gui/main.tsx b/apps/Test/gui/main.tsx deleted file mode 100644 index eb0a604..0000000 --- a/apps/Test/gui/main.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import ReactDOM from "react-dom/client"; -import App from "./App.tsx"; -import "./index.css"; - -ReactDOM.createRoot(document.getElementById("root")!).render(); diff --git a/apps/Test/gui/store/conversationStore.ts b/apps/Test/gui/store/conversationStore.ts deleted file mode 100644 index b1b10a8..0000000 --- a/apps/Test/gui/store/conversationStore.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { create } from "zustand"; - -interface conversationState { - assistantName: string; - conversationId: string; - receivingMsg: boolean; - setConversationId: (newId: string) => void; - setAssistantName: (newName: string) => void; - setReceivingMsg: (newState: boolean) => void; -} - -export const conversationStore = create()((set) => ({ - assistantName: "", - conversationId: "", - receivingMsg: false, - setConversationId: (newId) => set({ conversationId: newId }), - setAssistantName: (newName) => set({ assistantName: newName }), - setReceivingMsg: (newState) => set({ receivingMsg: newState }), -})); diff --git a/apps/Test/gui/store/messageStore.ts b/apps/Test/gui/store/messageStore.ts deleted file mode 100644 index 852c1e7..0000000 --- a/apps/Test/gui/store/messageStore.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { create } from "zustand"; - -interface messageState { - messages: Array<{ user: boolean; content: string }>; - pushMessage: (newMessage: { user: boolean; content: string }) => void; - resetConversation: () => void; -} - -export const messageStore = create()((set) => ({ - messages: [], - pushMessage: (newMessage) => - set((state) => ({ messages: [...state.messages, newMessage] })), - resetConversation: () => set(() => ({ messages: [] })), -})); diff --git a/apps/Test/gui/utils/request.ts b/apps/Test/gui/utils/request.ts deleted file mode 100644 index 510253d..0000000 --- a/apps/Test/gui/utils/request.ts +++ /dev/null @@ -1,16 +0,0 @@ -export async function httpRequest( - method: string, - endpoint: string, - body: object | null, -) { - const url = "/api" + endpoint; - const data = { - method: method, - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(body), - credentials: "include" as RequestCredentials, - }; - return await fetch(url, data).then((response) => response.json()); -} diff --git a/apps/Test/gui/vite-env.d.ts b/apps/Test/gui/vite-env.d.ts deleted file mode 100644 index 11f02fe..0000000 --- a/apps/Test/gui/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/apps/Test/index.html b/apps/Test/index.html deleted file mode 100644 index fa5f058..0000000 --- a/apps/Test/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - Test - - -
- - - diff --git a/apps/Test/package.json b/apps/Test/package.json deleted file mode 100644 index 1432b98..0000000 --- a/apps/Test/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "Test", - "private": true, - "version": "0.0.7", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc && vite build", - "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", - "preview": "vite preview" - }, - "dependencies": { - "@banorte/chat-ui": "workspace:*", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-markdown": "^9.0.1", - "react-spring": "^9.7.4", - "rehype-raw": "^7.0.0", - "sse.js": "^2.5.0", - "zustand": "^4.5.2" - }, - "devDependencies": { - "@iconify-icon/react": "^2.1.0", - "@types/react": "^18.2.67", - "@types/react-dom": "^18.2.22", - "@typescript-eslint/eslint-plugin": "^7.3.1", - "@typescript-eslint/parser": "^7.3.1", - "@vitejs/plugin-react": "^4.2.1", - "autoprefixer": "^10.4.19", - "daisyui": "^4.7.3", - "eslint": "^8.57.0", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.6", - "postcss": "^8.4.38", - "tailwind-scrollbar": "^3.1.0", - "tailwindcss": "^3.4.1", - "typescript": "^5.4.3", - "vite": "^5.2.3" - } -} diff --git a/apps/Test/postcss.config.js b/apps/Test/postcss.config.js deleted file mode 100644 index 2e7af2b..0000000 --- a/apps/Test/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} diff --git a/apps/Test/pyproject.toml b/apps/Test/pyproject.toml deleted file mode 100644 index 2d3973d..0000000 --- a/apps/Test/pyproject.toml +++ /dev/null @@ -1,18 +0,0 @@ -[project] -name = "Test" -version = "0.1.0" -description = "Add your description here" -readme = "README.md" -requires-python = ">=3.12, <4" -dependencies = [ - "aiohttp>=3.11.16", - "fastapi>=0.115.6", - "hvac>=2.3.0", - "langchain-azure-ai[opentelemetry]>=0.1.4", - "mongo-memory", - "pydantic-settings>=2.8.1", - "uvicorn>=0.34.0", -] - -[tool.uv.sources] -mongo-memory = { workspace = true } diff --git a/apps/Test/tailwind.config.js b/apps/Test/tailwind.config.js deleted file mode 100644 index 1e964c3..0000000 --- a/apps/Test/tailwind.config.js +++ /dev/null @@ -1,27 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -export default { - content: ["./index.html", "./gui/**/*.{js,ts,jsx,tsx}"], - theme: { - extend: { - backgroundImage: { - "navigation-pattern": "url('./assets/navigation.webp')", - }, - }, - }, - plugins: [ - require("daisyui"), - require("tailwind-scrollbar"), - require("@banorte/chat-ui/tailwind") - ], - daisyui: { - themes: [ - { - light: { - ...require("daisyui/src/theming/themes")["light"], - primary: "red", - secondary: "teal", - }, - }, - ], - }, -}; diff --git a/apps/Test/tsconfig.json b/apps/Test/tsconfig.json deleted file mode 100644 index 2f0d3e5..0000000 --- a/apps/Test/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2023", - "useDefineForClassFields": true, - "lib": ["ES2023", "DOM", "DOM.Iterable", "ES2021.String"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["gui"], - "references": [{ "path": "./tsconfig.node.json" }] -} diff --git a/apps/Test/tsconfig.node.json b/apps/Test/tsconfig.node.json deleted file mode 100644 index 97ede7e..0000000 --- a/apps/Test/tsconfig.node.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true, - "strict": true - }, - "include": ["vite.config.ts"] -} diff --git a/apps/Test/vite.config.ts b/apps/Test/vite.config.ts deleted file mode 100644 index 58f5a85..0000000 --- a/apps/Test/vite.config.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [react()], - server: { - host: "0.0.0.0", - port: 3000, - proxy: { - "/api": { - target: "http://localhost:8000", - }, - }, - allowedHosts: true, - }, -}); diff --git a/apps/bursatil/.k8s/deployment.yaml b/apps/bursatil/.k8s/deployment.yaml new file mode 100644 index 0000000..c9ed2eb --- /dev/null +++ b/apps/bursatil/.k8s/deployment.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mayacontigo-bursatil + namespace: apps + labels: + app: mayacontigo-bursatil +spec: + replicas: 1 + selector: + matchLabels: + app: mayacontigo-bursatil + template: + metadata: + labels: + app: mayacontigo-bursatil + spec: + imagePullSecrets: + - name: gitea-registry-cred + containers: + - name: mayacontigo-bursatil + image: gitea.ia-innovacion.work/innovacion/mayacontigo-bursatil:latest + env: + - name: VAULT_TOKEN + valueFrom: + secretKeyRef: + name: mayacontigo-bursatil-secret + key: VAULT_TOKEN + ports: + - containerPort: 80 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 15 + periodSeconds: 20 diff --git a/apps/bursatil/.k8s/ingress.yaml b/apps/bursatil/.k8s/ingress.yaml new file mode 100644 index 0000000..09ce6e1 --- /dev/null +++ b/apps/bursatil/.k8s/ingress.yaml @@ -0,0 +1,19 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: mayacontigo-bursatil-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + ingressClassName: nginx + rules: + - host: mayacontigo-bursatil.app.ia-innovacion.work + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: mayacontigo-bursatil-service + port: + number: 80 diff --git a/apps/bursatil/.k8s/secrets.yaml b/apps/bursatil/.k8s/secrets.yaml new file mode 100644 index 0000000..f075c5f --- /dev/null +++ b/apps/bursatil/.k8s/secrets.yaml @@ -0,0 +1,17 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: mayacontigo-bursatil-vault + namespace: apps +spec: + refreshInterval: "15s" + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: mayacontigo-bursatil-secret + data: + - secretKey: VAULT_TOKEN + remoteRef: + key: mayacontigo-bursatil + property: VAULT_TOKEN diff --git a/apps/bursatil/.k8s/service.yaml b/apps/bursatil/.k8s/service.yaml new file mode 100644 index 0000000..70a9957 --- /dev/null +++ b/apps/bursatil/.k8s/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: mayacontigo-bursatil-service + labels: + app: mayacontigo-bursatil +spec: + selector: + app: mayacontigo-bursatil + ports: + - port: 80 + targetPort: 80 + protocol: TCP + type: ClusterIP diff --git a/apps/ChatEgresos/.eslintrc.cjs b/apps/egresos/.eslintrc.cjs similarity index 100% rename from apps/ChatEgresos/.eslintrc.cjs rename to apps/egresos/.eslintrc.cjs diff --git a/apps/egresos/.k8s/deployment.yaml b/apps/egresos/.k8s/deployment.yaml new file mode 100644 index 0000000..8bbf1ee --- /dev/null +++ b/apps/egresos/.k8s/deployment.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mayacontigo-egresos + namespace: apps + labels: + app: mayacontigo-egresos +spec: + replicas: 1 + selector: + matchLabels: + app: mayacontigo-egresos + template: + metadata: + labels: + app: mayacontigo-egresos + spec: + imagePullSecrets: + - name: gitea-registry-cred + containers: + - name: mayacontigo-egresos + image: gitea.ia-innovacion.work/innovacion/mayacontigo-egresos:latest + env: + - name: VAULT_TOKEN + valueFrom: + secretKeyRef: + name: mayacontigo-egresos-secret + key: VAULT_TOKEN + ports: + - containerPort: 80 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 15 + periodSeconds: 20 diff --git a/apps/egresos/.k8s/ingress.yaml b/apps/egresos/.k8s/ingress.yaml new file mode 100644 index 0000000..135133d --- /dev/null +++ b/apps/egresos/.k8s/ingress.yaml @@ -0,0 +1,19 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: mayacontigo-egresos-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + ingressClassName: nginx + rules: + - host: mayacontigo-egresos.app.ia-innovacion.work + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: mayacontigo-egresos-service + port: + number: 80 diff --git a/apps/egresos/.k8s/secrets.yaml b/apps/egresos/.k8s/secrets.yaml new file mode 100644 index 0000000..949e669 --- /dev/null +++ b/apps/egresos/.k8s/secrets.yaml @@ -0,0 +1,17 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: mayacontigo-egresos-vault + namespace: apps +spec: + refreshInterval: "15s" + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: mayacontigo-egresos-secret + data: + - secretKey: VAULT_TOKEN + remoteRef: + key: mayacontigo-egresos + property: VAULT_TOKEN diff --git a/apps/egresos/.k8s/service.yaml b/apps/egresos/.k8s/service.yaml new file mode 100644 index 0000000..840cbd5 --- /dev/null +++ b/apps/egresos/.k8s/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: mayacontigo-egresos-service + labels: + app: mayacontigo-egresos +spec: + selector: + app: mayacontigo-egresos + ports: + - port: 80 + targetPort: 80 + protocol: TCP + type: ClusterIP diff --git a/apps/ChatEgresos/api/__init__.py b/apps/egresos/api/__init__.py similarity index 100% rename from apps/ChatEgresos/api/__init__.py rename to apps/egresos/api/__init__.py diff --git a/apps/ChatEgresos/api/agent/__init__.py b/apps/egresos/api/agent/__init__.py similarity index 100% rename from apps/ChatEgresos/api/agent/__init__.py rename to apps/egresos/api/agent/__init__.py diff --git a/apps/ChatEgresos/api/agent/main.py b/apps/egresos/api/agent/main.py similarity index 100% rename from apps/ChatEgresos/api/agent/main.py rename to apps/egresos/api/agent/main.py diff --git a/apps/ChatEgresos/api/agent/system_prompt.md b/apps/egresos/api/agent/system_prompt.md similarity index 100% rename from apps/ChatEgresos/api/agent/system_prompt.md rename to apps/egresos/api/agent/system_prompt.md diff --git a/apps/ChatEgresos/api/config.py b/apps/egresos/api/config.py similarity index 100% rename from apps/ChatEgresos/api/config.py rename to apps/egresos/api/config.py diff --git a/apps/ChatEgresos/api/context.py b/apps/egresos/api/context.py similarity index 100% rename from apps/ChatEgresos/api/context.py rename to apps/egresos/api/context.py diff --git a/apps/ChatEgresos/api/server.py b/apps/egresos/api/server.py similarity index 74% rename from apps/ChatEgresos/api/server.py rename to apps/egresos/api/server.py index f418840..917279b 100644 --- a/apps/ChatEgresos/api/server.py +++ b/apps/egresos/api/server.py @@ -1,11 +1,11 @@ -import uuid import time +import uuid from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.responses import StreamingResponse -from pydantic import BaseModel from langfuse import Langfuse +from pydantic import BaseModel from api import services from api.agent import Agent @@ -14,10 +14,11 @@ from api.config import config # Configurar Langfuse langfuse = Langfuse( public_key="pk-lf-49cb04b3-0c7d-475b-8105-ad8b8749ecdd", - secret_key="sk-lf-e02fa322-c709-4d80-bef2-9cb279846a0c", - host="https://ailogger.azurewebsites.net" + secret_key="sk-lf-e02fa322-c709-4d80-bef2-9cb279846a0c", + host="https://ailogger.azurewebsites.net", ) + @asynccontextmanager async def lifespan(_: FastAPI): await config.init_mongo_db() @@ -39,6 +40,7 @@ class Message(BaseModel): conversation_id: uuid.UUID prompt: str + @app.post("/api/v1/message") async def send(message: Message): # Crear trace principal @@ -47,66 +49,68 @@ async def send(message: Message): session_id=str(message.conversation_id), input={ "prompt": message.prompt, - "conversation_id": str(message.conversation_id) - } + "conversation_id": str(message.conversation_id), + }, ) - + def b64_sse(func): async def wrapper(*args, **kwargs): response_parts = [] start_time = time.time() - + async for chunk in func(*args, **kwargs): if chunk.type == "text" and chunk.content: response_parts.append(str(chunk.content)) - + content = chunk.model_dump_json() data = f"data: {content}\n\n" yield data - + end_time = time.time() - latency_ms = round((end_time - start_time) * 1000) + latency_ms = round((end_time - start_time) * 1000) full_response = "".join(response_parts) - - - input_tokens = len(message.prompt.split()) * 1.3 + + input_tokens = len(message.prompt.split()) * 1.3 output_tokens = len(full_response.split()) * 1.3 total_tokens = int(input_tokens + output_tokens) - - - cost_per_1k_input = 0.03 - cost_per_1k_output = 0.06 - total_cost = (input_tokens/1000 * cost_per_1k_input) + (output_tokens/1000 * cost_per_1k_output) - - + + cost_per_1k_input = 0.03 + cost_per_1k_output = 0.06 + total_cost = (input_tokens / 1000 * cost_per_1k_input) + ( + output_tokens / 1000 * cost_per_1k_output + ) + trace.update( output={"response": full_response}, usage={ "input": int(input_tokens), - "output": int(output_tokens), + "output": int(output_tokens), "total": total_tokens, - "unit": "TOKENS" - } + "unit": "TOKENS", + }, ) - - + langfuse.score( trace_id=trace.id, name="latency", value=latency_ms, - comment=f"Response time: {latency_ms}ms" + comment=f"Response time: {latency_ms}ms", ) - - + langfuse.score( trace_id=trace.id, name="cost", value=round(total_cost, 4), - comment=f"Estimated cost: ${round(total_cost, 4)}" + comment=f"Estimated cost: ${round(total_cost, 4)}", ) return wrapper sse_stream = b64_sse(services.stream) generator = sse_stream(agent, message.prompt, message.conversation_id) - return StreamingResponse(generator, media_type="text/event-stream") \ No newline at end of file + return StreamingResponse(generator, media_type="text/event-stream") + + +@app.get("/") +async def health(): + return {"status": "ok"} diff --git a/apps/ChatEgresos/api/services/__init__.py b/apps/egresos/api/services/__init__.py similarity index 100% rename from apps/ChatEgresos/api/services/__init__.py rename to apps/egresos/api/services/__init__.py diff --git a/apps/ChatEgresos/api/services/stream_response.py b/apps/egresos/api/services/stream_response.py similarity index 100% rename from apps/ChatEgresos/api/services/stream_response.py rename to apps/egresos/api/services/stream_response.py diff --git a/apps/ChatEgresos/gui/App.tsx b/apps/egresos/gui/App.tsx similarity index 100% rename from apps/ChatEgresos/gui/App.tsx rename to apps/egresos/gui/App.tsx diff --git a/apps/ChatEgresos/gui/assets/banortelogo.png b/apps/egresos/gui/assets/banortelogo.png similarity index 100% rename from apps/ChatEgresos/gui/assets/banortelogo.png rename to apps/egresos/gui/assets/banortelogo.png diff --git a/apps/ChatEgresos/gui/assets/brujula.png b/apps/egresos/gui/assets/brujula.png similarity index 100% rename from apps/ChatEgresos/gui/assets/brujula.png rename to apps/egresos/gui/assets/brujula.png diff --git a/apps/ChatEgresos/gui/assets/brujula_elipse.png b/apps/egresos/gui/assets/brujula_elipse.png similarity index 100% rename from apps/ChatEgresos/gui/assets/brujula_elipse.png rename to apps/egresos/gui/assets/brujula_elipse.png diff --git a/apps/ChatEgresos/gui/assets/chat_maya_boton_enviar.png b/apps/egresos/gui/assets/chat_maya_boton_enviar.png similarity index 100% rename from apps/ChatEgresos/gui/assets/chat_maya_boton_enviar.png rename to apps/egresos/gui/assets/chat_maya_boton_enviar.png diff --git a/apps/ChatEgresos/gui/assets/chat_maya_default_avatar.png b/apps/egresos/gui/assets/chat_maya_default_avatar.png similarity index 100% rename from apps/ChatEgresos/gui/assets/chat_maya_default_avatar.png rename to apps/egresos/gui/assets/chat_maya_default_avatar.png diff --git a/apps/ChatEgresos/gui/assets/sidebar_maya_contigo.png b/apps/egresos/gui/assets/sidebar_maya_contigo.png similarity index 100% rename from apps/ChatEgresos/gui/assets/sidebar_maya_contigo.png rename to apps/egresos/gui/assets/sidebar_maya_contigo.png diff --git a/apps/ChatEgresos/gui/index.css b/apps/egresos/gui/index.css similarity index 100% rename from apps/ChatEgresos/gui/index.css rename to apps/egresos/gui/index.css diff --git a/apps/ChatEgresos/gui/main.tsx b/apps/egresos/gui/main.tsx similarity index 100% rename from apps/ChatEgresos/gui/main.tsx rename to apps/egresos/gui/main.tsx diff --git a/apps/ChatEgresos/gui/store/conversationStore.ts b/apps/egresos/gui/store/conversationStore.ts similarity index 100% rename from apps/ChatEgresos/gui/store/conversationStore.ts rename to apps/egresos/gui/store/conversationStore.ts diff --git a/apps/ChatEgresos/gui/store/messageStore.ts b/apps/egresos/gui/store/messageStore.ts similarity index 100% rename from apps/ChatEgresos/gui/store/messageStore.ts rename to apps/egresos/gui/store/messageStore.ts diff --git a/apps/ChatEgresos/gui/utils/request.ts b/apps/egresos/gui/utils/request.ts similarity index 100% rename from apps/ChatEgresos/gui/utils/request.ts rename to apps/egresos/gui/utils/request.ts diff --git a/apps/ChatEgresos/gui/vite-env.d.ts b/apps/egresos/gui/vite-env.d.ts similarity index 100% rename from apps/ChatEgresos/gui/vite-env.d.ts rename to apps/egresos/gui/vite-env.d.ts diff --git a/apps/ChatEgresos/index.html b/apps/egresos/index.html similarity index 100% rename from apps/ChatEgresos/index.html rename to apps/egresos/index.html diff --git a/apps/ChatEgresos/package.json b/apps/egresos/package.json similarity index 100% rename from apps/ChatEgresos/package.json rename to apps/egresos/package.json diff --git a/apps/ChatEgresos/postcss.config.js b/apps/egresos/postcss.config.js similarity index 100% rename from apps/ChatEgresos/postcss.config.js rename to apps/egresos/postcss.config.js diff --git a/apps/ChatEgresos/pyproject.toml b/apps/egresos/pyproject.toml similarity index 95% rename from apps/ChatEgresos/pyproject.toml rename to apps/egresos/pyproject.toml index 9a1eee5..d90441b 100644 --- a/apps/ChatEgresos/pyproject.toml +++ b/apps/egresos/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "ChatEgresos" +name = "egresos" version = "0.1.0" description = "Add your description here" readme = "README.md" diff --git a/apps/ChatEgresos/readme.md b/apps/egresos/readme.md similarity index 100% rename from apps/ChatEgresos/readme.md rename to apps/egresos/readme.md diff --git a/apps/ChatEgresos/tailwind.config.js b/apps/egresos/tailwind.config.js similarity index 100% rename from apps/ChatEgresos/tailwind.config.js rename to apps/egresos/tailwind.config.js diff --git a/apps/ChatEgresos/tsconfig.json b/apps/egresos/tsconfig.json similarity index 100% rename from apps/ChatEgresos/tsconfig.json rename to apps/egresos/tsconfig.json diff --git a/apps/ChatEgresos/tsconfig.node.json b/apps/egresos/tsconfig.node.json similarity index 100% rename from apps/ChatEgresos/tsconfig.node.json rename to apps/egresos/tsconfig.node.json diff --git a/apps/ChatEgresos/vite.config.ts b/apps/egresos/vite.config.ts similarity index 100% rename from apps/ChatEgresos/vite.config.ts rename to apps/egresos/vite.config.ts diff --git a/apps/normativa/.k8s/deployment.yaml b/apps/normativa/.k8s/deployment.yaml new file mode 100644 index 0000000..7196868 --- /dev/null +++ b/apps/normativa/.k8s/deployment.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mayacontigo-normativa + namespace: apps + labels: + app: mayacontigo-normativa +spec: + replicas: 1 + selector: + matchLabels: + app: mayacontigo-normativa + template: + metadata: + labels: + app: mayacontigo-normativa + spec: + imagePullSecrets: + - name: gitea-registry-cred + containers: + - name: mayacontigo-normativa + image: gitea.ia-innovacion.work/innovacion/mayacontigo-normativa:latest + env: + - name: VAULT_TOKEN + valueFrom: + secretKeyRef: + name: mayacontigo-normativa-secret + key: VAULT_TOKEN + ports: + - containerPort: 80 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 15 + periodSeconds: 20 diff --git a/apps/normativa/.k8s/ingress.yaml b/apps/normativa/.k8s/ingress.yaml new file mode 100644 index 0000000..d57c033 --- /dev/null +++ b/apps/normativa/.k8s/ingress.yaml @@ -0,0 +1,19 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: mayacontigo-normativa-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + ingressClassName: nginx + rules: + - host: mayacontigo-normativa.app.ia-innovacion.work + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: mayacontigo-normativa-service + port: + number: 80 diff --git a/apps/normativa/.k8s/secrets.yaml b/apps/normativa/.k8s/secrets.yaml new file mode 100644 index 0000000..4c9f3eb --- /dev/null +++ b/apps/normativa/.k8s/secrets.yaml @@ -0,0 +1,17 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: mayacontigo-normativa-vault + namespace: apps +spec: + refreshInterval: "15s" + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: mayacontigo-normativa-secret + data: + - secretKey: VAULT_TOKEN + remoteRef: + key: mayacontigo-normativa + property: VAULT_TOKEN diff --git a/apps/normativa/.k8s/service.yaml b/apps/normativa/.k8s/service.yaml new file mode 100644 index 0000000..11c7278 --- /dev/null +++ b/apps/normativa/.k8s/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: mayacontigo-normativa-service + labels: + app: mayacontigo-normativa +spec: + selector: + app: mayacontigo-normativa + ports: + - port: 80 + targetPort: 80 + protocol: TCP + type: ClusterIP diff --git a/apps/normativa/api/server.py b/apps/normativa/api/server.py index c466594..29f7abd 100644 --- a/apps/normativa/api/server.py +++ b/apps/normativa/api/server.py @@ -1,15 +1,14 @@ -import uuid import os +import uuid from contextlib import asynccontextmanager from pathlib import Path +from dotenv import load_dotenv # ← Agregar este import from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware -from fastapi.responses import StreamingResponse, FileResponse, RedirectResponse -from pydantic import BaseModel +from fastapi.responses import FileResponse, RedirectResponse, StreamingResponse from langfuse import Langfuse - -from dotenv import load_dotenv # ← Agregar este import +from pydantic import BaseModel from api import services from api.agent import Agent @@ -21,8 +20,8 @@ load_dotenv() # Configurar Langfuse desde variables de entorno langfuse = Langfuse( public_key=os.getenv("LANGFUSE_PUBLIC_KEY"), - secret_key=os.getenv("LANGFUSE_SECRET_KEY"), - host=os.getenv("LANGFUSE_HOST") + secret_key=os.getenv("LANGFUSE_SECRET_KEY"), + host=os.getenv("LANGFUSE_HOST"), ) @@ -34,12 +33,10 @@ PDF_PUBLIC_URLS = { "Disposiciones de carácter general aplicables a las sociedades controladoras de grupos financieros y subcontroladoras que regulan las materias que corresponden de manera conjunta a las Comisio.pdf": "https://www.cnbv.gob.mx/Normatividad/Disposiciones%20de%20car%C3%A1cter%20general%20aplicables%20a%20las%20sociedades%20controladoras%20de%20grupos%20financieros%20y%20subcontroladoras%20que%20regulan%20las%20materias%20que%20corresponden%20de%20manera%20conjunta%20a%20las%20Comisiones%20Nacionales%20Supervisoras.pdf", "Disposiciones de carácter general aplicables a los fondos de inversión y a las personas que les prestan servicios.pdf": "https://www.cnbv.gob.mx/Normatividad/Disposiciones%20de%20car%C3%A1cter%20general%20aplicables%20a%20los%20fondos%20de%20inversi%C3%B3n%20y%20a%20las%20personas%20que%20les%20prestan%20servicios.pdf", "Ley para la Transparencia y Ordenamiento de los Servicios Financieros.pdf": "https://www.cnbv.gob.mx/Normatividad/Ley%20para%20la%20Transparencia%20y%20Ordenamiento%20de%20los%20Servicios%20Financieros.pdf", - # Circulares CNBV adicionales "circular_servicios_de_inversion.pdf": "https://www.cnbv.gob.mx/Normatividad/Disposiciones%20de%20car%C3%A1cter%20general%20aplicables%20a%20las%20entidades%20financieras%20y%20dem%C3%A1s%20personas%20que%20proporcionen%20servicios%20de.pdf", "circular_unica_de_auditores_externos.pdf": "https://www.cnbv.gob.mx/Normatividad/Disposiciones%20de%20car%C3%A1cter%20general%20que%20establecen%20los%20requisitos%20que%20deber%C3%A1n%20cumplir%20los%20auditores%20y%20otros%20profesionales%20que.pdf", "ley_de_instituciones_de_Credito.pdf": "https://www.cnbv.gob.mx/Normatividad/Ley%20de%20Instituciones%20de%20Cr%C3%A9dito.pdf", - # Circulares de Banxico "circular_13_2007.pdf": "https://www.banxico.org.mx/marco-normativo/normativa-emitida-por-el-banco-de-mexico/circular-13-2007/cobro-intereses-por-adelantad.html", "circular_13_2011.pdf": "https://www.banxico.org.mx/marco-normativo/normativa-emitida-por-el-banco-de-mexico/circular-13-2011/%7BBA4CBC28-A468-16C9-6F17-9EA9D7B03318%7D.pdf", @@ -55,15 +52,12 @@ PDF_PUBLIC_URLS = { "circular_36_2010.pdf": "https://www.banxico.org.mx/marco-normativo/normativa-emitida-por-el-banco-de-mexico/circular-36-2010/%7B26C55DE6-CC3A-3368-34FC-1A6C50B11130%7D.pdf", "circular_3_2012.pdf": "https://www.banxico.org.mx/marco-normativo/normativa-emitida-por-el-banco-de-mexico/circular-3-2012/%7B4E0281A4-7AD8-1462-BC79-7F2925F3171D%7D.pdf", "circular_4_2012.pdf": "https://www.banxico.org.mx/marco-normativo/normativa-emitida-por-el-banco-de-mexico/circular-4-2012/%7B97C62974-1C94-19AE-AB5A-D0D949A36247%7D.pdf", - # CONDUSEF "circular_unica_de_condusef.pdf": "https://www.condusef.gob.mx/documentos/marco_legal/disposiciones-transparencia-if-sofom.pdf", "ley_para_regular_las_sociedades_de_informacion_crediticia.pdf": "https://www.condusef.gob.mx/documentos/marco_legal/disposiciones-transparencia-if-sofom.pdf", - # Leyes federales "ley_federal_de_proteccion_de_datos_personales_en_posesion_de_los_particulares.pdf": "https://www.diputados.gob.mx/LeyesBiblio/pdf/LFPDPPP.pdf", "reglamento_de_la_ley_federal_de_proteccion_de_datos_personales_en_posesion_de_los_particulares.pdf": "https://www.diputados.gob.mx/LeyesBiblio/regley/Reg_LFPDPPP.pdf", - # SharePoint Banorte "Modificaciones Recursos Procedencia Ilícita jul 25 PLD.pdf": "https://gfbanorte.sharepoint.com/:w:/r/sites/Formatosyplantillas/Documentos%20compartidos/Otros/Modificaciones%20Recursos%20Procedencia%20Il%C3%ADcita%20jul%2025%20PLD.docx?d=w6a941e9e2c26403ea41c12de35536516&csf=1&web=1&e=EHtc9b", } @@ -79,17 +73,17 @@ app = FastAPI(lifespan=lifespan) app.add_middleware( CORSMiddleware, - allow_origins=["*"], + allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], - expose_headers=["*"] + expose_headers=["*"], ) agent = Agent() PDF_FOLDER = Path(__file__).parent / "agent" / "pdf" -PDF_FOLDER.mkdir(parents=True, exist_ok=True) +PDF_FOLDER.mkdir(parents=True, exist_ok=True) @app.post("/api/v1/conversation") @@ -110,21 +104,21 @@ async def send(message: Message): trace = langfuse.trace( name="rag_chat", session_id=str(message.conversation_id), - input={"prompt": message.prompt} + input={"prompt": message.prompt}, ) - + def b64_sse(func): async def wrapper(*args, **kwargs): response_parts = [] - + async for chunk in func(*args, **kwargs): if chunk.type == "text" and chunk.content: response_parts.append(str(chunk.content)) - + content = chunk.model_dump_json() data = f"data: {content}\n\n" yield data - + # Solo registrar input y output full_response = "".join(response_parts) trace.update(output={"response": full_response}) @@ -139,17 +133,21 @@ async def send(message: Message): @app.get("/api/pdf/{filename}") async def get_pdf(filename: str): print(f"🔍 Solicitud PDF para: {filename}") - - if not filename.lower().endswith('.pdf'): + + if not filename.lower().endswith(".pdf"): print(f"❌ Archivo no es PDF: {filename}") raise HTTPException(status_code=400, detail="El archivo debe ser un PDF") - - if '..' in filename or ('/' in filename and not filename.startswith('http')) or '\\' in filename: + + if ( + ".." in filename + or ("/" in filename and not filename.startswith("http")) + or "\\" in filename + ): print(f"❌ Nombre de archivo inválido: {filename}") raise HTTPException(status_code=400, detail="Nombre de archivo inválido") - + public_url = PDF_PUBLIC_URLS.get(filename) - + if public_url: print(f"✅ Redirigiendo a URL pública: {public_url}") return RedirectResponse( @@ -159,39 +157,41 @@ async def get_pdf(filename: str): "Cache-Control": "public, max-age=3600", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, OPTIONS", - "Access-Control-Allow-Headers": "*" - } + "Access-Control-Allow-Headers": "*", + }, ) - + pdf_path = PDF_FOLDER / filename - + if not pdf_path.exists(): print(f"❌ PDF no encontrado: {pdf_path}") - raise HTTPException(status_code=404, detail=f"PDF no encontrado. Archivo: {filename}") - + raise HTTPException( + status_code=404, detail=f"PDF no encontrado. Archivo: {filename}" + ) + if not pdf_path.is_file(): print(f"❌ No es un archivo: {pdf_path}") raise HTTPException(status_code=404, detail="El recurso no es un archivo") - + file_size = pdf_path.stat().st_size print(f"📄 Sirviendo archivo local: {filename} ({file_size} bytes)") - + if file_size == 0: print(f"❌ Archivo vacío: {pdf_path}") raise HTTPException(status_code=500, detail="El archivo PDF está vacío") - + return FileResponse( path=str(pdf_path), media_type="application/pdf", filename=filename, headers={ - "Content-Disposition": f"inline; filename={filename}", + "Content-Disposition": f"inline; filename={filename}", "Content-Type": "application/pdf", "Cache-Control": "public, max-age=3600", - "X-Frame-Options": "ALLOWALL", + "X-Frame-Options": "ALLOWALL", "X-Content-Type-Options": "nosniff", - "Access-Control-Allow-Origin": "*" - } + "Access-Control-Allow-Origin": "*", + }, ) @@ -199,29 +199,33 @@ async def get_pdf(filename: str): async def list_pdfs(): try: pdf_files = [] - + for filename, url in PDF_PUBLIC_URLS.items(): - pdf_files.append({ - "filename": filename, - "size": "N/A (Público)", - "url": f"/api/pdf/{filename}", - "public_url": url, - "type": "public" - }) - + pdf_files.append( + { + "filename": filename, + "size": "N/A (Público)", + "url": f"/api/pdf/{filename}", + "public_url": url, + "type": "public", + } + ) + local_files = [] for pattern in ["*.pdf", "*.PDF"]: for file_path in PDF_FOLDER.glob(pattern): if file_path.is_file() and file_path.name not in PDF_PUBLIC_URLS: - local_files.append({ - "filename": file_path.name, - "size": file_path.stat().st_size, - "url": f"/api/pdf/{file_path.name}", - "type": "local" - }) - + local_files.append( + { + "filename": file_path.name, + "size": file_path.stat().st_size, + "url": f"/api/pdf/{file_path.name}", + "type": "local", + } + ) + pdf_files.extend(local_files) - + debug_info = { "current_working_directory": str(Path.cwd()), "pdf_folder_path": str(PDF_FOLDER.absolute()), @@ -230,52 +234,49 @@ async def list_pdfs(): "local_files_count": len(local_files), "public_files": list(PDF_PUBLIC_URLS.keys()), } - - return { - "pdfs": pdf_files, - "debug": debug_info, - "total_pdfs": len(pdf_files) - } + + return {"pdfs": pdf_files, "debug": debug_info, "total_pdfs": len(pdf_files)} except Exception as e: import traceback + return { "error": str(e), "traceback": traceback.format_exc(), "debug": { "current_working_directory": str(Path.cwd()), - "script_file_path": __file__ if '__file__' in globals() else "unknown" - } + "script_file_path": __file__ if "__file__" in globals() else "unknown", + }, } @app.get("/api/pdf/{filename}/info") async def get_pdf_info(filename: str): - if not filename.lower().endswith('.pdf'): + if not filename.lower().endswith(".pdf"): raise HTTPException(status_code=400, detail="El archivo debe ser un PDF") - - if '..' in filename or '/' in filename or '\\' in filename: + + if ".." in filename or "/" in filename or "\\" in filename: raise HTTPException(status_code=400, detail="Nombre de archivo inválido") - + public_url = PDF_PUBLIC_URLS.get(filename) if public_url: return { "filename": filename, "size": "N/A", - "size_mb": "N/A", + "size_mb": "N/A", "modified": "N/A", "url": f"/api/pdf/{filename}", "public_url": public_url, - "type": "public" + "type": "public", } - + pdf_path = PDF_FOLDER / filename - + if not pdf_path.exists(): raise HTTPException(status_code=404, detail="PDF no encontrado") - + if not pdf_path.is_file(): raise HTTPException(status_code=404, detail="El recurso no es un archivo") - + try: file_stat = pdf_path.stat() return { @@ -284,10 +285,12 @@ async def get_pdf_info(filename: str): "size_mb": round(file_stat.st_size / (1024 * 1024), 2), "modified": file_stat.st_mtime, "url": f"/api/pdf/{filename}", - "type": "local" + "type": "local", } except Exception as e: - raise HTTPException(status_code=500, detail=f"Error al obtener información del PDF: {str(e)}") + raise HTTPException( + status_code=500, detail=f"Error al obtener información del PDF: {str(e)}" + ) @app.get("/api/health") @@ -296,5 +299,10 @@ async def health_check(): "status": "healthy", "pdf_folder": str(PDF_FOLDER), "pdf_folder_exists": PDF_FOLDER.exists(), - "public_urls_configured": len(PDF_PUBLIC_URLS) - } \ No newline at end of file + "public_urls_configured": len(PDF_PUBLIC_URLS), + } + + +@app.get("/") +async def health(): + return {"status": "ok"} diff --git a/apps/pyme/.k8s/deployment.yaml b/apps/pyme/.k8s/deployment.yaml new file mode 100644 index 0000000..5b6623b --- /dev/null +++ b/apps/pyme/.k8s/deployment.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mayacontigo-pyme + namespace: apps + labels: + app: mayacontigo-pyme +spec: + replicas: 1 + selector: + matchLabels: + app: mayacontigo-pyme + template: + metadata: + labels: + app: mayacontigo-pyme + spec: + imagePullSecrets: + - name: gitea-registry-cred + containers: + - name: mayacontigo-pyme + image: gitea.ia-innovacion.work/innovacion/mayacontigo-pyme:latest + env: + - name: VAULT_TOKEN + valueFrom: + secretKeyRef: + name: mayacontigo-pyme-secret + key: VAULT_TOKEN + ports: + - containerPort: 80 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 15 + periodSeconds: 20 diff --git a/apps/pyme/.k8s/ingress.yaml b/apps/pyme/.k8s/ingress.yaml new file mode 100644 index 0000000..b860f7d --- /dev/null +++ b/apps/pyme/.k8s/ingress.yaml @@ -0,0 +1,19 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: mayacontigo-pyme-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + ingressClassName: nginx + rules: + - host: mayacontigo-pyme.app.ia-innovacion.work + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: mayacontigo-pyme-service + port: + number: 80 diff --git a/apps/pyme/.k8s/secrets.yaml b/apps/pyme/.k8s/secrets.yaml new file mode 100644 index 0000000..a203882 --- /dev/null +++ b/apps/pyme/.k8s/secrets.yaml @@ -0,0 +1,17 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: mayacontigo-pyme-vault + namespace: apps +spec: + refreshInterval: "15s" + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: mayacontigo-pyme-secret + data: + - secretKey: VAULT_TOKEN + remoteRef: + key: mayacontigo-pyme + property: VAULT_TOKEN diff --git a/apps/pyme/.k8s/service.yaml b/apps/pyme/.k8s/service.yaml new file mode 100644 index 0000000..462c173 --- /dev/null +++ b/apps/pyme/.k8s/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: mayacontigo-pyme-service + labels: + app: mayacontigo-pyme +spec: + selector: + app: mayacontigo-pyme + ports: + - port: 80 + targetPort: 80 + protocol: TCP + type: ClusterIP diff --git a/apps/pyme/api/server.py b/apps/pyme/api/server.py index ab0bfcd..2afa44e 100644 --- a/apps/pyme/api/server.py +++ b/apps/pyme/api/server.py @@ -1,15 +1,14 @@ -import uuid import os +import uuid from contextlib import asynccontextmanager from pathlib import Path +from dotenv import load_dotenv # ← Agregar este import from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware -from fastapi.responses import StreamingResponse, FileResponse, RedirectResponse -from pydantic import BaseModel +from fastapi.responses import FileResponse, RedirectResponse, StreamingResponse from langfuse import Langfuse - -from dotenv import load_dotenv # ← Agregar este import +from pydantic import BaseModel from api import services from api.agent import Agent @@ -21,14 +20,13 @@ load_dotenv() # Configurar Langfuse desde variables de entorno langfuse = Langfuse( public_key=os.getenv("LANGFUSE_PUBLIC_KEY"), - secret_key=os.getenv("LANGFUSE_SECRET_KEY"), - host=os.getenv("LANGFUSE_HOST") + secret_key=os.getenv("LANGFUSE_SECRET_KEY"), + host=os.getenv("LANGFUSE_HOST"), ) # Mapeo completo de archivos a URLs públicas -PDF_PUBLIC_URLS = { - } +PDF_PUBLIC_URLS = {} @asynccontextmanager @@ -41,17 +39,17 @@ app = FastAPI(lifespan=lifespan) app.add_middleware( CORSMiddleware, - allow_origins=["*"], + allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], - expose_headers=["*"] + expose_headers=["*"], ) agent = Agent() PDF_FOLDER = Path(__file__).parent / "agent" / "pdf" -PDF_FOLDER.mkdir(parents=True, exist_ok=True) +PDF_FOLDER.mkdir(parents=True, exist_ok=True) @app.post("/api/v1/conversation") @@ -72,21 +70,21 @@ async def send(message: Message): trace = langfuse.trace( name="rag_chat", session_id=str(message.conversation_id), - input={"prompt": message.prompt} + input={"prompt": message.prompt}, ) - + def b64_sse(func): async def wrapper(*args, **kwargs): response_parts = [] - + async for chunk in func(*args, **kwargs): if chunk.type == "text" and chunk.content: response_parts.append(str(chunk.content)) - + content = chunk.model_dump_json() data = f"data: {content}\n\n" yield data - + # Solo registrar input y output full_response = "".join(response_parts) trace.update(output={"response": full_response}) @@ -101,17 +99,21 @@ async def send(message: Message): @app.get("/api/pdf/{filename}") async def get_pdf(filename: str): print(f"🔍 Solicitud PDF para: {filename}") - - if not filename.lower().endswith('.pdf'): + + if not filename.lower().endswith(".pdf"): print(f"❌ Archivo no es PDF: {filename}") raise HTTPException(status_code=400, detail="El archivo debe ser un PDF") - - if '..' in filename or ('/' in filename and not filename.startswith('http')) or '\\' in filename: + + if ( + ".." in filename + or ("/" in filename and not filename.startswith("http")) + or "\\" in filename + ): print(f"❌ Nombre de archivo inválido: {filename}") raise HTTPException(status_code=400, detail="Nombre de archivo inválido") - + public_url = PDF_PUBLIC_URLS.get(filename) - + if public_url: print(f"✅ Redirigiendo a URL pública: {public_url}") return RedirectResponse( @@ -121,39 +123,41 @@ async def get_pdf(filename: str): "Cache-Control": "public, max-age=3600", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, OPTIONS", - "Access-Control-Allow-Headers": "*" - } + "Access-Control-Allow-Headers": "*", + }, ) - + pdf_path = PDF_FOLDER / filename - + if not pdf_path.exists(): print(f"❌ PDF no encontrado: {pdf_path}") - raise HTTPException(status_code=404, detail=f"PDF no encontrado. Archivo: {filename}") - + raise HTTPException( + status_code=404, detail=f"PDF no encontrado. Archivo: {filename}" + ) + if not pdf_path.is_file(): print(f"❌ No es un archivo: {pdf_path}") raise HTTPException(status_code=404, detail="El recurso no es un archivo") - + file_size = pdf_path.stat().st_size print(f"📄 Sirviendo archivo local: {filename} ({file_size} bytes)") - + if file_size == 0: print(f"❌ Archivo vacío: {pdf_path}") raise HTTPException(status_code=500, detail="El archivo PDF está vacío") - + return FileResponse( path=str(pdf_path), media_type="application/pdf", filename=filename, headers={ - "Content-Disposition": f"inline; filename={filename}", + "Content-Disposition": f"inline; filename={filename}", "Content-Type": "application/pdf", "Cache-Control": "public, max-age=3600", - "X-Frame-Options": "ALLOWALL", + "X-Frame-Options": "ALLOWALL", "X-Content-Type-Options": "nosniff", - "Access-Control-Allow-Origin": "*" - } + "Access-Control-Allow-Origin": "*", + }, ) @@ -161,29 +165,33 @@ async def get_pdf(filename: str): async def list_pdfs(): try: pdf_files = [] - + for filename, url in PDF_PUBLIC_URLS.items(): - pdf_files.append({ - "filename": filename, - "size": "N/A (Público)", - "url": f"/api/pdf/{filename}", - "public_url": url, - "type": "public" - }) - + pdf_files.append( + { + "filename": filename, + "size": "N/A (Público)", + "url": f"/api/pdf/{filename}", + "public_url": url, + "type": "public", + } + ) + local_files = [] for pattern in ["*.pdf", "*.PDF"]: for file_path in PDF_FOLDER.glob(pattern): if file_path.is_file() and file_path.name not in PDF_PUBLIC_URLS: - local_files.append({ - "filename": file_path.name, - "size": file_path.stat().st_size, - "url": f"/api/pdf/{file_path.name}", - "type": "local" - }) - + local_files.append( + { + "filename": file_path.name, + "size": file_path.stat().st_size, + "url": f"/api/pdf/{file_path.name}", + "type": "local", + } + ) + pdf_files.extend(local_files) - + debug_info = { "current_working_directory": str(Path.cwd()), "pdf_folder_path": str(PDF_FOLDER.absolute()), @@ -192,52 +200,49 @@ async def list_pdfs(): "local_files_count": len(local_files), "public_files": list(PDF_PUBLIC_URLS.keys()), } - - return { - "pdfs": pdf_files, - "debug": debug_info, - "total_pdfs": len(pdf_files) - } + + return {"pdfs": pdf_files, "debug": debug_info, "total_pdfs": len(pdf_files)} except Exception as e: import traceback + return { "error": str(e), "traceback": traceback.format_exc(), "debug": { "current_working_directory": str(Path.cwd()), - "script_file_path": __file__ if '__file__' in globals() else "unknown" - } + "script_file_path": __file__ if "__file__" in globals() else "unknown", + }, } @app.get("/api/pdf/{filename}/info") async def get_pdf_info(filename: str): - if not filename.lower().endswith('.pdf'): + if not filename.lower().endswith(".pdf"): raise HTTPException(status_code=400, detail="El archivo debe ser un PDF") - - if '..' in filename or '/' in filename or '\\' in filename: + + if ".." in filename or "/" in filename or "\\" in filename: raise HTTPException(status_code=400, detail="Nombre de archivo inválido") - + public_url = PDF_PUBLIC_URLS.get(filename) if public_url: return { "filename": filename, "size": "N/A", - "size_mb": "N/A", + "size_mb": "N/A", "modified": "N/A", "url": f"/api/pdf/{filename}", "public_url": public_url, - "type": "public" + "type": "public", } - + pdf_path = PDF_FOLDER / filename - + if not pdf_path.exists(): raise HTTPException(status_code=404, detail="PDF no encontrado") - + if not pdf_path.is_file(): raise HTTPException(status_code=404, detail="El recurso no es un archivo") - + try: file_stat = pdf_path.stat() return { @@ -246,10 +251,12 @@ async def get_pdf_info(filename: str): "size_mb": round(file_stat.st_size / (1024 * 1024), 2), "modified": file_stat.st_mtime, "url": f"/api/pdf/{filename}", - "type": "local" + "type": "local", } except Exception as e: - raise HTTPException(status_code=500, detail=f"Error al obtener información del PDF: {str(e)}") + raise HTTPException( + status_code=500, detail=f"Error al obtener información del PDF: {str(e)}" + ) @app.get("/api/health") @@ -258,5 +265,10 @@ async def health_check(): "status": "healthy", "pdf_folder": str(PDF_FOLDER), "pdf_folder_exists": PDF_FOLDER.exists(), - "public_urls_configured": len(PDF_PUBLIC_URLS) - } \ No newline at end of file + "public_urls_configured": len(PDF_PUBLIC_URLS), + } + + +@app.get("/") +async def health(): + return {"app": "RAG PyME", "status": "OK"} diff --git a/apps/riesgos/.k8s/deployment.yaml b/apps/riesgos/.k8s/deployment.yaml new file mode 100644 index 0000000..373379b --- /dev/null +++ b/apps/riesgos/.k8s/deployment.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mayacontigo-riesgos + namespace: apps + labels: + app: mayacontigo-riesgos +spec: + replicas: 1 + selector: + matchLabels: + app: mayacontigo-riesgos + template: + metadata: + labels: + app: mayacontigo-riesgos + spec: + imagePullSecrets: + - name: gitea-registry-cred + containers: + - name: mayacontigo-riesgos + image: gitea.ia-innovacion.work/innovacion/mayacontigo-riesgos:latest + env: + - name: VAULT_TOKEN + valueFrom: + secretKeyRef: + name: mayacontigo-riesgos-secret + key: VAULT_TOKEN + ports: + - containerPort: 80 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 15 + periodSeconds: 20 diff --git a/apps/riesgos/.k8s/ingress.yaml b/apps/riesgos/.k8s/ingress.yaml new file mode 100644 index 0000000..5169220 --- /dev/null +++ b/apps/riesgos/.k8s/ingress.yaml @@ -0,0 +1,19 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: mayacontigo-riesgos-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + ingressClassName: nginx + rules: + - host: mayacontigo-riesgos.app.ia-innovacion.work + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: mayacontigo-riesgos-service + port: + number: 80 diff --git a/apps/riesgos/.k8s/secrets.yaml b/apps/riesgos/.k8s/secrets.yaml new file mode 100644 index 0000000..639e4db --- /dev/null +++ b/apps/riesgos/.k8s/secrets.yaml @@ -0,0 +1,17 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: mayacontigo-riesgos-vault + namespace: apps +spec: + refreshInterval: "15s" + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: mayacontigo-riesgos-secret + data: + - secretKey: VAULT_TOKEN + remoteRef: + key: mayacontigo-riesgos + property: VAULT_TOKEN diff --git a/apps/riesgos/.k8s/service.yaml b/apps/riesgos/.k8s/service.yaml new file mode 100644 index 0000000..715bb7e --- /dev/null +++ b/apps/riesgos/.k8s/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: mayacontigo-riesgos-service + labels: + app: mayacontigo-riesgos +spec: + selector: + app: mayacontigo-riesgos + ports: + - port: 80 + targetPort: 80 + protocol: TCP + type: ClusterIP diff --git a/apps/riesgos/api/server/__init__.py b/apps/riesgos/api/server/__init__.py index f496973..8956316 100644 --- a/apps/riesgos/api/server/__init__.py +++ b/apps/riesgos/api/server/__init__.py @@ -20,4 +20,10 @@ app = FastAPI( openapi_url="/api/openapi.json", ) + +@app.get("/") +async def health(): + return {"status": "ok"} + + app.include_router(router) diff --git a/apps/voz-del-cliente/.k8s/deployment.yaml b/apps/voz-del-cliente/.k8s/deployment.yaml new file mode 100644 index 0000000..c8aefa7 --- /dev/null +++ b/apps/voz-del-cliente/.k8s/deployment.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mayacontigo-voz-del-cliente + namespace: apps + labels: + app: mayacontigo-voz-del-cliente +spec: + replicas: 1 + selector: + matchLabels: + app: mayacontigo-voz-del-cliente + template: + metadata: + labels: + app: mayacontigo-voz-del-cliente + spec: + imagePullSecrets: + - name: gitea-registry-cred + containers: + - name: mayacontigo-voz-del-cliente + image: gitea.ia-innovacion.work/innovacion/mayacontigo-voz-del-cliente:latest + env: + - name: VAULT_TOKEN + valueFrom: + secretKeyRef: + name: mayacontigo-voz-del-cliente-secret + key: VAULT_TOKEN + ports: + - containerPort: 80 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 15 + periodSeconds: 20 diff --git a/apps/voz-del-cliente/.k8s/ingress.yaml b/apps/voz-del-cliente/.k8s/ingress.yaml new file mode 100644 index 0000000..6953bea --- /dev/null +++ b/apps/voz-del-cliente/.k8s/ingress.yaml @@ -0,0 +1,19 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: mayacontigo-voz-del-cliente-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + ingressClassName: nginx + rules: + - host: mayacontigo-voz-del-cliente.app.ia-innovacion.work + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: mayacontigo-voz-del-cliente-service + port: + number: 80 diff --git a/apps/voz-del-cliente/.k8s/secrets.yaml b/apps/voz-del-cliente/.k8s/secrets.yaml new file mode 100644 index 0000000..2f28a92 --- /dev/null +++ b/apps/voz-del-cliente/.k8s/secrets.yaml @@ -0,0 +1,17 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: mayacontigo-voz-del-cliente-vault + namespace: apps +spec: + refreshInterval: "15s" + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: mayacontigo-voz-del-cliente-secret + data: + - secretKey: VAULT_TOKEN + remoteRef: + key: mayacontigo-voz-del-cliente + property: VAULT_TOKEN diff --git a/apps/voz-del-cliente/.k8s/service.yaml b/apps/voz-del-cliente/.k8s/service.yaml new file mode 100644 index 0000000..b97a689 --- /dev/null +++ b/apps/voz-del-cliente/.k8s/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: mayacontigo-voz-del-cliente-service + labels: + app: mayacontigo-voz-del-cliente +spec: + selector: + app: mayacontigo-voz-del-cliente + ports: + - port: 80 + targetPort: 80 + protocol: TCP + type: ClusterIP diff --git a/apps/voz-del-cliente/api/config.py b/apps/voz-del-cliente/api/config.py index 2f9057e..e50504b 100644 --- a/apps/voz-del-cliente/api/config.py +++ b/apps/voz-del-cliente/api/config.py @@ -1,9 +1,7 @@ from hvac import Client from pydantic import Field -from dotenv import load_dotenv from pydantic_settings import BaseSettings - client = Client(url="https://vault.ia-innovacion.work") if not client.is_authenticated(): @@ -14,6 +12,7 @@ secret_map = client.secrets.kv.v2.read_secret_version( )["data"]["data"] class Settings(BaseSettings): + """ Esta clase obtiene sus valores de variables de ambiente. Si no estan en el ambiente, los jala de nuestra Vault. @@ -39,11 +38,10 @@ class Settings(BaseSettings): async def init_mongo_db(self): """Este helper inicia la conexion enter el MongoDB ORM y nuestra instancia""" + from banortegpt.database.mongo_memory.models import Conversation from beanie import init_beanie from motor.motor_asyncio import AsyncIOMotorClient - from banortegpt.database.mongo_memory.models import Conversation - await init_beanie( database=AsyncIOMotorClient(self.mongodb_url).voz_del_cliente, document_models=[Conversation], diff --git a/apps/voz-del-cliente/api/server.py b/apps/voz-del-cliente/api/server.py index 471b410..2273935 100644 --- a/apps/voz-del-cliente/api/server.py +++ b/apps/voz-del-cliente/api/server.py @@ -35,16 +35,24 @@ class Message(BaseModel): @app.post("/api/v1/message") async def send(message: Message): - def b64_sse(func): """Este helper transforma un generador de strings a un generador del protocolo SSE""" + async def wrapper(*args, **kwargs): async for chunk in func(*args, **kwargs): content = chunk.model_dump_json() data = f"data: {content}\n\n" yield data + return wrapper sse_stream = b64_sse(services.stream) - generator = sse_stream(agent, message.prompt, message.conversation_id, message.with_deep_research) + generator = sse_stream( + agent, message.prompt, message.conversation_id, message.with_deep_research + ) return StreamingResponse(generator, media_type="text/event-stream") + + +@app.get("/") +async def health(): + return {"app": "Voz del Cliente", "status": "OK"} diff --git a/compose.yaml b/compose.yaml index 5f6cdd3..7e3fea9 100644 --- a/compose.yaml +++ b/compose.yaml @@ -45,16 +45,16 @@ services: - traefik.http.routers.ocp.entrypoints=web - traefik.http.routers.ocp.middlewares=ocp-strip - traefik.http.middlewares.ocp-strip.stripprefix.prefixes=/api/mayaocp - ChatEgresos: - image: mayacontigo/chategresos:latest + egresos: + image: mayacontigo/egresos:latest build: context: . dockerfile: .containers/unit/Dockerfile args: - PACKAGE: ChatEgresos + PACKAGE: egresos x-bake: tags: - - mayacontigo/chategresos:latest + - mayacontigo/egresos:latest ports: - 8001:80 labels: @@ -69,7 +69,7 @@ services: context: . dockerfile: .containers/unit/Dockerfile args: - PACKAGE: nnormativa + PACKAGE: voz-del-cliente x-bake: tags: - mayacontigo/nnormativa:latest @@ -99,42 +99,6 @@ services: - traefik.http.routers.normativa.entrypoints=web - traefik.http.routers.normativa.middlewares=normativa-strip - traefik.http.middlewares.normativa-strip.stripprefix.prefixes=/api/mayanormativa - Test: - image: mayacontigo/Test:latest - build: - context: . - dockerfile: .containers/unit/Dockerfile - args: - PACKAGE: Test - x-bake: - tags: - - mayacontigo/Test:latest - ports: - - 8002:80 - labels: - - traefik.enable=true - - traefik.http.routers.Test.rule=PathPrefix(`/api/mayaTest`) - - traefik.http.routers.Test.entrypoints=web - - traefik.http.routers.Test.middlewares=Test-strip - - traefik.http.middlewares.Test-strip.stripprefix.prefixes=/api/mayaTest - nnormativa: - image: mayacontigo/nnormativa:latest - build: - context: . - dockerfile: .containers/unit/Dockerfile - args: - PACKAGE: nnormativa - x-bake: - tags: - - mayacontigo/nnormativa:latest - ports: - - 8003:80 - labels: - - traefik.enable=true - - traefik.http.routers.nnormativa.rule=PathPrefix(`/api/mayannormativa`) - - traefik.http.routers.nnormativa.entrypoints=web - - traefik.http.routers.nnormativa.middlewares=nnormativa-strip - - traefik.http.middlewares.nnormativa-strip.stripprefix.prefixes=/api/mayannormativa pyme: image: mayacontigo/pyme:latest build: diff --git a/scripts/replace-app-name.sh b/scripts/replace-app-name.sh new file mode 100755 index 0000000..0b29b94 --- /dev/null +++ b/scripts/replace-app-name.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Replace app name in Kubernetes manifest files +# Usage: ./replace-app-name.sh +# Example: ./replace-app-name.sh bursatil inversionistas + +if [ $# -ne 2 ]; then + echo "Usage: $0 " + echo "Example: $0 bursatil inversionistas" + exit 1 +fi + +APP_NAME=$1 +OLD_NAME=$2 +K8S_DIR="apps/$APP_NAME/.k8s" + +if [ ! -d "$K8S_DIR" ]; then + echo "Error: Directory $K8S_DIR does not exist" + exit 1 +fi + +echo "Replacing '$OLD_NAME' with '$APP_NAME' in $K8S_DIR" + +for file in "$K8S_DIR"/*.yaml; do + if [ -f "$file" ]; then + echo " Processing: $(basename $file)" + sed -i "s/$OLD_NAME/$APP_NAME/g" "$file" + fi +done + +echo "Done!" diff --git a/uv.lock b/uv.lock index 1790cf6..4cb5e2f 100644 --- a/uv.lock +++ b/uv.lock @@ -13,8 +13,8 @@ members = [ "azure-storage", "banortegpt", "bursatil", - "chategresos", "chunk-with-llm", + "egresos", "google-storage", "inversionistas", "mongo-memory", @@ -27,7 +27,6 @@ members = [ "riesgos", "search-evaluator", "synthetic-question-generator", - "test", "vector-db-migrator", "vertex-ai-gemini", "voz-del-cliente", @@ -503,33 +502,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", size = 52626, upload-time = "2025-05-02T08:34:40.053Z" }, ] -[[package]] -name = "chategresos" -version = "0.1.0" -source = { virtual = "apps/ChatEgresos" } -dependencies = [ - { name = "aiohttp" }, - { name = "fastapi" }, - { name = "hvac" }, - { name = "langchain-azure-ai", extra = ["opentelemetry"] }, - { name = "mongo-memory" }, - { name = "pydantic-settings" }, - { name = "qdrant" }, - { name = "uvicorn" }, -] - -[package.metadata] -requires-dist = [ - { name = "aiohttp", specifier = ">=3.11.16" }, - { name = "fastapi", specifier = ">=0.115.6" }, - { name = "hvac", specifier = ">=2.3.0" }, - { name = "langchain-azure-ai", extras = ["opentelemetry"], specifier = ">=0.1.4" }, - { name = "mongo-memory", editable = "packages/mongo-memory" }, - { name = "pydantic-settings", specifier = ">=2.8.1" }, - { name = "qdrant", editable = "packages/qdrant" }, - { name = "uvicorn", specifier = ">=0.34.0" }, -] - [[package]] name = "chunk-with-llm" version = "0.1.0" @@ -749,6 +721,33 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, ] +[[package]] +name = "egresos" +version = "0.1.0" +source = { virtual = "apps/egresos" } +dependencies = [ + { name = "aiohttp" }, + { name = "fastapi" }, + { name = "hvac" }, + { name = "langchain-azure-ai", extra = ["opentelemetry"] }, + { name = "mongo-memory" }, + { name = "pydantic-settings" }, + { name = "qdrant" }, + { name = "uvicorn" }, +] + +[package.metadata] +requires-dist = [ + { name = "aiohttp", specifier = ">=3.11.16" }, + { name = "fastapi", specifier = ">=0.115.6" }, + { name = "hvac", specifier = ">=2.3.0" }, + { name = "langchain-azure-ai", extras = ["opentelemetry"], specifier = ">=0.1.4" }, + { name = "mongo-memory", editable = "packages/mongo-memory" }, + { name = "pydantic-settings", specifier = ">=2.8.1" }, + { name = "qdrant", editable = "packages/qdrant" }, + { name = "uvicorn", specifier = ">=0.34.0" }, +] + [[package]] name = "email-validator" version = "2.2.0" @@ -3438,31 +3437,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, ] -[[package]] -name = "test" -version = "0.1.0" -source = { virtual = "apps/Test" } -dependencies = [ - { name = "aiohttp" }, - { name = "fastapi" }, - { name = "hvac" }, - { name = "langchain-azure-ai", extra = ["opentelemetry"] }, - { name = "mongo-memory" }, - { name = "pydantic-settings" }, - { name = "uvicorn" }, -] - -[package.metadata] -requires-dist = [ - { name = "aiohttp", specifier = ">=3.11.16" }, - { name = "fastapi", specifier = ">=0.115.6" }, - { name = "hvac", specifier = ">=2.3.0" }, - { name = "langchain-azure-ai", extras = ["opentelemetry"], specifier = ">=0.1.4" }, - { name = "mongo-memory", editable = "packages/mongo-memory" }, - { name = "pydantic-settings", specifier = ">=2.8.1" }, - { name = "uvicorn", specifier = ">=0.34.0" }, -] - [[package]] name = "tiktoken" version = "0.9.0"