<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Bruno Curtarelli on Medium]]></title>
        <description><![CDATA[Stories by Bruno Curtarelli on Medium]]></description>
        <link>https://medium.com/@bruno.curtarelli?source=rss-b49dc1830fc6------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*BN6sUBcI0ynOnC612yO2_g.png</url>
            <title>Stories by Bruno Curtarelli on Medium</title>
            <link>https://medium.com/@bruno.curtarelli?source=rss-b49dc1830fc6------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 14:31:59 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@bruno.curtarelli/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Gata Guru: Uma Aplicação de Chat Inteligente com IA para Análise de Dados]]></title>
            <link>https://medium.com/petlabs/gata-guru-uma-aplica%C3%A7%C3%A3o-de-chat-inteligente-com-ia-para-an%C3%A1lise-de-dados-9e491dda3eb2?source=rss-b49dc1830fc6------2</link>
            <guid isPermaLink="false">https://medium.com/p/9e491dda3eb2</guid>
            <category><![CDATA[openai]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[pet-love]]></category>
            <category><![CDATA[data-analysis]]></category>
            <category><![CDATA[agents]]></category>
            <dc:creator><![CDATA[Bruno Curtarelli]]></dc:creator>
            <pubDate>Tue, 24 Jun 2025 12:10:51 GMT</pubDate>
            <atom:updated>2025-06-24T15:13:38.378Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Op6V1WrIfIsOiK7g6SUHyQ.png" /><figcaption>A Gata Guru</figcaption></figure><h3>Introdução</h3><p>A <strong>Gata Guru</strong> é uma aplicação moderna de chatbot desenvolvida para facilitar a análise de dados corporativos da Petlove através de interface conversacional com Inteligência Artificial. Esta solução representa um exemplo prático de como integrar tecnologias de IA com ferramentas de análise de dados em uma arquitetura escalável e bem estruturada.</p><h3>Como funciona a Gata Guru?</h3><p>O Gata Guru é um sistema modular de chat inteligente que permite aos usuários fazerem perguntas sobre os dados disponíveis no Catálogo de dados e DW da Petlove e receber respostas inteligentes geradas por IA. A Gata Guru também possui acesso ao Bigquery e tem permissão para rodar queries e extrais dados para responder as perguntas dos usuários.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*6jvJBg8EV3MYhJFTuFuTow.gif" /><figcaption>Gata Guru em ação</figcaption></figure><h3>Principais Funcionalidades</h3><ul><li>💬 <strong>Chat Inteligente</strong>: Interface conversacional responsiva em Streamlit</li><li>🧠 <strong>IA Avançada</strong>: Integração com modelos mais modernos da OpenAI</li><li>📊 <strong>Análise de Dados</strong>: Consultas automáticas no BigQuery</li><li>🔐 <strong>Segurança</strong>: Autenticação OAuth com domínio corporativo</li><li>📈 <strong>Visualizações</strong>: Dashboards e gráficos interativos</li><li>🔍 <strong>Catálogo de Dados</strong>: Acesso a metadados e documentação</li><li>🐛 <strong>Monitoramento</strong>: Tracking de erros com Honeybadger</li></ul><h3>Arquitetura da Aplicação</h3><h4>Visão Geral da Arquitetura</h4><p>A Gata Guru foi desenvolvida seguindo princípios de <strong>arquitetura modular </strong>e <strong>Clean Code</strong>, onde cada componente tem responsabilidades bem definidas e pode ser desenvolvido, testado e mantido independentemente.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*v3P8K7-OFEy7s59FSw2ieg.png" /><figcaption>Arquitetura do sistema da Gata Guru</figcaption></figure><h3>Componentes Principais</h3><h4>1. Gataguru System (chat/gataguru_system.py)</h4><ul><li><strong>Responsabilidade</strong>: Orquestração geral do sistema</li><li><strong>Funções</strong>: Inicialização, configuração e coordenação de componentes</li><li><strong>Características</strong>: Ponto central que integra todos os módulos</li></ul><h4>2. Conversation Manager (chat/conversation_manager.py)</h4><ul><li><strong>Responsabilidade</strong>: Processamento de mensagens e orquestração de agentes</li><li><strong>Funções</strong>: Execução de agentes especializados, Processamento de respostas, Gerenciamento de contexto de conversa, Montagem de conversas estruturadas</li></ul><h4>3. Agent Factory (chat/agent_factory.py)</h4><ul><li><strong>Responsabilidade</strong>: Criação e configuração de agentes especializados</li><li><strong>Tipos de Agentes</strong>:</li><li><strong>Intern Agent</strong>: Para tarefas básicas e consultas simples</li><li><strong>Expert Agent</strong>: Para análises complexas e especializadas</li><li><strong>Data Manager Agent</strong>: Para gerenciamento de dados e metadados</li></ul><h4>4. Agents Tools (chat/agents_tools.py)</h4><ul><li><strong>Responsabilidade</strong>: Ferramentas para interação com BigQuery e catálogo de dados</li><li><strong>Funcionalidades</strong>: Execução de consultas SQL no BigQuery, Acesso ao catálogo de dados corporativo, Modelo Pydantic para análise de dados estruturada</li></ul><h4>5. Interface de Compatibilidade (chat/custom_agents.py)</h4><ul><li><strong>Responsabilidade</strong>: Manter compatibilidade com código existente</li><li><strong>Funções</strong>: Wrappers para funções como a answers() para processar as mensagens na IA e assemble_conversation() para organizar os históricos de mensagens</li></ul><h3>Stack Tecnológica</h3><h3>Frontend e Interface</h3><h4>Streamlit (v1.32+)</h4><ul><li><strong>Propósito</strong>: Framework web para aplicações de dados em Python</li><li><strong>Vantagens</strong>:</li><li>Desenvolvimento rápido de interfaces</li><li>Integração nativa com ecossistema Python</li><li>Componentes interativos prontos para uso</li><li>Suporte a autenticação OAuth</li></ul><h4>CSS Customizado</h4><ul><li><strong>Tema personalizado</strong> para interface moderna</li><li><strong>Design responsivo</strong> para desktop e mobile</li><li><strong>Componentes visuais</strong> customizados</li></ul><h3>Backend e Processamento</h3><h4>Python 3.9+</h4><ul><li><strong>Linguagem principal</strong> do projeto</li><li><strong>Tipagem estática</strong> com typing-extensions</li><li><strong>Estruturas de dados</strong> com Pydantic</li></ul><h4>OpenAI GPT-4</h4><ul><li><strong>Modelo de linguagem</strong> para processamento de perguntas</li><li><strong>Geração de respostas</strong> inteligentes e contextualizadas</li><li><strong>Integração via API</strong> oficial da OpenAI</li></ul><h3>Armazenamento e Dados</h3><h4>Google BigQuery</h4><ul><li><strong>Data warehouse</strong> para consultas de dados corporativos</li><li><strong>Integração via Google Cloud SDK</strong></li><li><strong>Service Account</strong> para autenticação segura</li></ul><h4>Data Catalog API — OpenMetaData</h4><ul><li><strong>Metadados</strong> e documentação de dados</li><li><strong>Descoberta</strong> de datasets disponíveis</li><li><strong>Governança</strong> de dados corporativos</li></ul><h3>Qualidade e Monitoramento</h3><h4>Honeybadger</h4><ul><li><strong>Error tracking</strong> em produção</li><li><strong>Monitoramento</strong> de performance</li><li><strong>Alertas</strong> automáticos para problemas</li></ul><h4>Pytest</h4><ul><li><strong>Framework de testes</strong> unitários</li><li><strong>55 testes</strong> automatizados</li><li><strong>Cobertura</strong> de código abrangente</li></ul><h4>Ruff</h4><ul><li><strong>Linting</strong> e formatação de código</li><li><strong>Padrões</strong> de qualidade automatizados</li><li><strong>Integração</strong> com pre-commit hooks</li></ul><h3>Autenticação e Segurança</h3><h4>Google OAuth</h4><ul><li><strong>Autenticação</strong> com contas Google</li><li><strong>Domínio corporativo</strong> restrito (@petlove.com.br)</li><li><strong>Integração</strong> nativa com Streamlit</li></ul><h4>Authlib</h4><ul><li><strong>Biblioteca OAuth</strong> para Python</li><li><strong>Gerenciamento</strong> de tokens e sessões</li></ul><h3>Estrutura do Projeto</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/898/1*ZuHHfPTdFz5Dy5P-MZD3fA.png" /><figcaption>Estrutura do repositório</figcaption></figure><h3>Fluxo de funcionamento</h3><h4>1. Autenticação do Usuário</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/856/1*LOQRtZilADlukHpCUkmAJQ.png" /></figure><h4>2. Processamento de Perguntas</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*d2Q750Q7-26In4nlK4LaJg.png" /></figure><h3>Benefícios da Arquitetura Modular</h3><h4>✅ Separação de Responsabilidades</h4><p>Cada componente tem uma função específica e bem definida, facilitando manutenção e evolução.</p><h4>✅ Facilidade de Testes</h4><p>Componentes isolados são mais fáceis de testar individualmente, resultando em 55 testes automatizados.</p><h4>✅ Escalabilidade</h4><p>Novos agentes e ferramentas podem ser adicionados sem afetar componentes existentes.</p><h4>✅ Reutilização</h4><p>Componentes podem ser reutilizados em outros projetos ou aplicações.</p><h4>✅ Debugging</h4><p>Problemas são mais fáceis de isolar e corrigir devido à modularidade.</p><h3>Monitoramento e Observabilidade</h3><h4>Honeybadger Integration</h4><ul><li><strong>Error tracking</strong> automático</li><li><strong>Contexto</strong> de usuário e sessão</li><li><strong>Alertas</strong> em tempo real</li><li><strong>Métricas</strong> de performance</li></ul><h4>Logging Estruturado</h4><ul><li><strong>Logs</strong> em português brasileiro</li><li><strong>Níveis</strong> de log apropriados</li><li><strong>Contexto</strong> rico para debugging</li></ul><h4>Qualidade de Código</h4><h4>Padrões de Desenvolvimento</h4><ul><li><strong>Docstrings</strong> em português brasileiro</li><li><strong>Tipagem</strong> estática com type hints</li><li><strong>Formatação</strong> automática com Ruff</li><li><strong>Pre-commit hooks</strong> para qualidade</li></ul><h4>Testes Automatizados</h4><ul><li><strong>55 testes unitários</strong></li><li><strong>Cobertura</strong> abrangente</li><li><strong>Integração</strong> com CI/CD</li><li><strong>Execução</strong> automática no commit</li></ul><h4>Traces</h4><ul><li>Monitoramento dos agentes e uso das ferramentas direto na Openai</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7MhsZxZfCxaXPhberF3Iqw.png" /><figcaption>Exemplo de um trace na Openai</figcaption></figure><h3>Conclusão</h3><p>A <strong>Gata Guru</strong> representa um exemplo moderno de aplicação de IA para análise de dados, demonstrando como integrar diferentes tecnologias em uma arquitetura escalável e bem estruturada. A escolha de frameworks e tecnologias foi cuidadosamente planejada para:</p><ul><li><strong>Facilitar o desenvolvimento</strong> com Streamlit e Python</li><li><strong>Garantir qualidade</strong> com testes e ferramentas de linting</li><li><strong>Proporcionar escalabilidade</strong> com arquitetura modular</li><li><strong>Assegurar segurança</strong> com autenticação OAuth</li><li><strong>Manter observabilidade</strong> com monitoramento robusto</li></ul><p>A aplicação serve como referência para desenvolvimento de soluções similares, mostrando como combinar IA, análise de dados e boas práticas de engenharia de software em um projeto real e funcional.</p><blockquote>Projeto desenvolvido pelo time de IA da Petlove, agradecimentos especiais ao time de Plataforma (Ray), SRE (Lucas) e Security (Marcelo)</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9e491dda3eb2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/petlabs/gata-guru-uma-aplica%C3%A7%C3%A3o-de-chat-inteligente-com-ia-para-an%C3%A1lise-de-dados-9e491dda3eb2">Gata Guru: Uma Aplicação de Chat Inteligente com IA para Análise de Dados</a> was originally published in <a href="https://medium.com/petlabs">Petlabs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to track OpenAI costs effectively?]]></title>
            <link>https://medium.com/petlabs/how-to-track-openai-costs-effectively-fb8e2c2dd44?source=rss-b49dc1830fc6------2</link>
            <guid isPermaLink="false">https://medium.com/p/fb8e2c2dd44</guid>
            <category><![CDATA[cost-tracking]]></category>
            <category><![CDATA[data]]></category>
            <category><![CDATA[pet-love]]></category>
            <category><![CDATA[openai]]></category>
            <category><![CDATA[chatgpt]]></category>
            <dc:creator><![CDATA[Bruno Curtarelli]]></dc:creator>
            <pubDate>Thu, 24 Aug 2023 19:46:16 GMT</pubDate>
            <atom:updated>2023-08-24T20:03:04.005Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*vZK5veIIfZNnf6bv" /><figcaption>Photo by <a href="https://unsplash.com/@maria_shalabaieva?utm_source=medium&amp;utm_medium=referral">Mariia Shalabaieva</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Since we’ve started using OpenAI here ate <a href="http://petlove.com.br/">Petlove</a>, one of the main concerns was about keep tracking of its costs. We could not find good benchmarks and most of the information available was about cots per tokens and strategies to estimate data processing based on that.</p><p>OpenAI <a href="https://platform.openai.com/">platform</a> do offers a usage tracking, but it is very limited and do not bring any detail about usage trends by customer, model and other breaks.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/730/1*rSYNvPXxQXvgaWaORcib0A.png" /><figcaption><a href="https://platform.openai.com/account/usage">https://platform.openai.com/account/usage</a>: daily/cumulative usage in US, by month + usage breakdowns by day and member</figcaption></figure><p>If you want to know the spent by member or by model you have to dig into daily usage breakdown dropdown menus, searching day by day, or copy/pasting information to organize a more consolidated view.</p><p>Looking for help at the internet I could find some posts, like <a href="https://medium.com/@mcraddock/managing-openai-api-costs-strategies-and-best-practices-9b5d09eb2426">this</a> from <a href="https://medium.com/u/1ca79a11bc85">Mark Craddock</a> which he explains good strategies and suggest using the API response to build your own dashboard.</p><p>Also, searching at <a href="https://community.openai.com/">OpenAI community</a> resources, I could find several discussions about this need and in <a href="https://community.openai.com/t/how-to-track-individual-usage/15935/36">this topic</a> I found a partial solution from <a href="https://community.openai.com/u/davell">Davell</a>, which I mixed with the idea of attributing the <a href="https://openai.com/pricing">right pricing info</a> from OpenAI platform table.</p><p>The objective of this post is to bring more details on how to build that cost tracking using OpenAI API response and a bit of python code to make a simple cost tracking tool with more detailed view.</p><p>To start, we are using the following packages:</p><pre>import json  # to work on request responses and storage data<br>import requests # call API<br>import datetime # parse dates<br>from dateutil.relativedelta import relativedelta # date manipulation<br>import dateutil.parser as dparser # parse dates from strings<br><br>import os # get environment vars<br>import pandas as pd # you probably wrote this one before I tell<br>import time # sleeper to avoid exceeding API limits</pre><p>Then you can get your OpenAI credentials stored in env vars:</p><pre>openai_org_id = os.getenv(&#39;OPENAI_ORG_ID&#39;)<br>openai_api_key = os.getenv(&#39;OPENAI_API_KEY&#39;)</pre><p>Since I was running it locally, I have specified a working directory in which I’m saving the json files with the API extractions. So I start reading the json files stored in this working directory to get the last date extracted from the API:</p><pre>files = []<br>[files.append(f) for f in os.listdir() if f.endswith(&#39;.json&#39;)]<br>files.sort()<br><br>fdates = {}<br><br>idate = datetime.date(2023, 7, 1) # initial date<br><br>for f in files:<br>    dates = []<br>    for i in f.split(&#39;_&#39;):<br>        try:<br>            dparser.parse(i, fuzzy=True)<br>            <br>            if dparser.parse(i, fuzzy=True).date()&gt;idate:<br>                <br>                first_day_of_month=dparser.parse(i, fuzzy=True).date()<br>                <br>            dates.append(dparser.parse(i, fuzzy=True)) <br>            <br>        except ValueError:<br>            <br>            pass<br>        <br>    fdates[f] = dates<br>    <br>first_day += relativedelta(days=1) # adding 1 day to start from the day after last extraction<br>current_day = datetime.date.today() #end date</pre><p>Next step is to prepare API headers and extract the list of members in the organization:</p><pre>headers = {<br>    &quot;method&quot;: &quot;GET&quot;,<br>    &quot;authority&quot;: &quot;api.openai.com&quot;,<br>    &quot;scheme&quot;: &quot;https&quot;,<br>    &quot;path&quot;: f&quot;/v1/organizations/{openai_org_id}/users&quot;,<br>    &quot;authorization&quot;: f&quot;Bearer {openai_api_key}&quot;,<br>}<br><br>starttime = time.monotonic() #starting to count time because the following request counts for the usage limits<br><br>users_response = requests.get(f&quot;https://api.openai.com/v1/organizations/{openai_org_id}/users&quot;, headers=headers)<br>users = users_response.json()[&quot;members&quot;][&quot;data&quot;]</pre><p>Now we create a iteration over members and dates which we want to extract the API data:</p><pre>df_costs = pd.DataFrame() #empty dataframe to store the data extracted<br><br>for user in users:<br>    <br>    id_of_user = user[&quot;user&quot;][&quot;id&quot;]<br><br>    current_date = first_day<br>    <br>    while current_date &lt; current_day and True:<br>        <br>        # I was giving 15 seconds just to ensure the requests per minute would not break the limits<br>        time.sleep(15.0 - ((time.monotonic() - starttime) % 15.0))<br>        <br>        usage_headers = {<br>            &quot;method&quot;: &quot;GET&quot;,<br>            &quot;authority&quot;: &quot;api.openai.com&quot;,<br>            &quot;authorization&quot;: f&quot;Bearer {openai_api_key}&quot;,<br>            &quot;openai-organization&quot;: openai_org_id,<br>        }<br>        <br>        usage_response = requests.get(f&quot;https://api.openai.com/v1/usage?date={current_date}&amp;user_public_id={id_of_user}&quot;, headers=usage_headers)<br>        user_data = usage_response.json()<br>     <br>        # This conditional is to avoid breaking if the response is empty<br>        if len(user_data[&#39;data&#39;])==0:<br>            <br>            current_date += relativedelta(days=1)<br>            <br>            continue<br>            <br>        else:<br>            <br>            data = user_data[&quot;data&quot;]<br>            <br>            # This condition is to parse whisper model response in the same structure as the GPT/Embeddings models<br>            if len(user_data[&#39;whisper_api_data&#39;])&gt;0:<br>                <br>                wad = []<br>                for w in user_data[&#39;whisper_api_data&#39;]:<br>                    wd={}<br>                    wd[&#39;aggregation_timestamp&#39;] = w[&#39;timestamp&#39;]<br>                    wd[&#39;n_requests&#39;] = w[&#39;num_requests&#39;]<br>                    wd[&#39;operation&#39;] = &#39;audio-whisper&#39;<br>                    wd[&#39;snapshot_id&#39;] = w[&#39;model_id&#39;]<br>                    wd[&#39;n_context&#39;] = w[&#39;num_seconds&#39;]<br>                    wd[&#39;n_context_tokens_total&#39;] = w[&#39;num_seconds&#39;]<br>                    wd[&#39;n_generated&#39;] = 0<br>                    wd[&#39;n_generated_tokens_total&#39;] = 0<br>                    wad = wad + [wd]<br>                data = data + wad<br>                <br>            else:<br>                <br>                pass<br>              <br>            df = pd.DataFrame(data)<br>            df[&#39;local_timestamp&#39;] = df[&#39;aggregation_timestamp&#39;].apply(lambda x: datetime.datetime.fromtimestamp(x))<br>            # converting to openai tz<br>            df[&#39;system_timestamp&#39;] = df[&#39;local_timestamp&#39;].dt.tz_localize(&#39;America/Sao_Paulo&#39;).dt.tz_convert(&quot;UTC&quot;)<br>            df[&#39;user&#39;] = user[&quot;user&quot;][&quot;name&quot;].lower().replace(&quot; &quot;, &quot;_&quot;)<br>            df[&#39;email&#39;] = user[&quot;user&quot;][&quot;email&quot;]<br><br>            df_costs = pd.concat([df_costs,df])<br><br>            current_date += relativedelta(days=1)</pre><p>After running the extratcions you can take a look into you df_costs dataframe using df_costs.head()</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ddf576ba8fb8eb51d800f8100262bfa3/href">https://medium.com/media/ddf576ba8fb8eb51d800f8100262bfa3/href</a></iframe><p>Here we are building the model costs parameters:</p><pre>model_costs = {<br>    &quot;gpt-3.5-turbo&quot;: {&quot;context&quot;: 0.0015, &quot;generated&quot;: 0.002},<br>    &quot;gpt-3.5-turbo-0301&quot;: {&quot;context&quot;: 0.0015, &quot;generated&quot;: 0.002},<br>    &quot;gpt-3.5-turbo-0613&quot;: {&quot;context&quot;: 0.0015, &quot;generated&quot;: 0.002},<br>    &quot;gpt-3.5-turbo-16k&quot;: {&quot;context&quot;: 0.003, &quot;generated&quot;: 0.004},<br>    &quot;gpt-3.5-turbo-16k-0613&quot;: {&quot;context&quot;: 0.003, &quot;generated&quot;: 0.004},<br>    &quot;gpt-4&quot;: {&quot;context&quot;: 0.03, &quot;generated&quot;: 0.06},<br>    &quot;gpt-4-0314&quot;: {&quot;context&quot;: 0.03, &quot;generated&quot;: 0.06},<br>    &quot;gpt-4-0613&quot;: {&quot;context&quot;: 0.03, &quot;generated&quot;: 0.06},<br>    &quot;gpt-4-32k&quot;: {&quot;context&quot;: 0.06, &quot;generated&quot;: 0.12},<br>    &quot;gpt-4-32k-0314&quot;: {&quot;context&quot;: 0.06, &quot;generated&quot;: 0.12},<br>    &quot;gpt-4-32k-0613&quot;: {&quot;context&quot;: 0.06, &quot;generated&quot;: 0.12},<br>    &quot;text-embedding-ada-002-v2&quot;: {&quot;context&quot;: 0.0001, &quot;generated&quot;: 0},<br>    &quot;text-davinci:003&quot;: {&quot;context&quot;: 0.02, &quot;generated&quot;: 0.02},<br>    &quot;whisper-1&quot;: {&quot;context&quot;: 0.1, &quot;generated&quot;: 0}, # costs are 0.006 per min (or 0.0001 per second). Multiplying by x1000 to use same rules as tokens<br>}<br><br>mc = pd.DataFrame(model_costs)<br>mc = mc.T.reset_index()</pre><p>And now we can apply the cost rates over the API consumption extracted into df_costs:</p><pre>df_costs=df_costs.merge(mc, left_on=&#39;snapshot_id&#39;, right_on=&#39;index&#39;, how=&#39;left&#39;)<br>df_costs[&#39;context_costs&#39;]=(df_costs[&#39;n_context_tokens_total&#39;]/1000)*df_costs[&#39;context&#39;]<br>df_costs[&#39;generated_costs&#39;]=(df_costs[&#39;n_generated_tokens_total&#39;]/1000)*df_costs[&#39;generated&#39;]<br>df_costs[&#39;total_costs&#39;]=df_costs[&#39;context_costs&#39;]+df_costs[&#39;generated_costs&#39;]</pre><p>The next block of code is to show how I was concatenating the current extraction to past extractions in my local working directory:</p><pre>try:<br>    past_df = pd.read_json(files[len(files)-1])<br>    df_costs = pd.concat([df_costs, past_df])<br>except FileNotFoundError:<br>    pass<br>df_costs.reset_index(drop=&#39;level_0&#39;, inplace=True)<br><br># ensuring datetime formats<br>df_costs[&#39;local_timestamp&#39;] = pd.to_datetime(df_costs[&#39;local_timestamp&#39;])<br>df_costs[&#39;system_timestamp&#39;] = pd.to_datetime(df_costs[&#39;system_timestamp&#39;])<br><br># saving a json file    <br>with open(f&quot;openai_costs_{idate}_to_{current_date - datetime.timedelta(days=1)}.json&quot;, &quot;w&quot;) as f:<br>    json.dump(json.loads(df_costs.to_json(orient=&#39;columns&#39;, date_format=&#39;iso&#39;)), f)</pre><p>This is the end of the data extraction step.</p><p>Now that we have the data, let’s explore how to make some charts using them. First lets import the packages for dataviz:</p><pre>import matplotlib<br>import matplotlib.pyplot as plt<br>import seaborn as sns<br>%matplotlib inline</pre><p>Then we create a function to aggregate data and compute the indicators:</p><pre>def summary_costs(x):<br>    names = {<br>        &#39;requests&#39;: x[&#39;n_requests&#39;].sum()<br>        , &#39;context_tokens&#39;: x[&#39;n_context_tokens_total&#39;].sum()<br>        , &#39;generated_tokens&#39;: x[&#39;n_generated_tokens_total&#39;].sum()<br>        , &#39;context_costs&#39;: x[&#39;context_costs&#39;].sum()<br>        , &#39;generated_costs&#39;: x[&#39;generated_costs&#39;].sum()<br>        , &#39;total_costs&#39;: x[&#39;total_costs&#39;].sum()<br>    }<br>    <br>    return pd.Series(names, index=[&#39;requests&#39;<br>                                   , &#39;context_tokens&#39;<br>                                   , &#39;generated_tokens&#39;<br>                                   , &#39;context_costs&#39;<br>                                   , &#39;generated_costs&#39;<br>                                   , &#39;total_costs&#39;<br>                                  ])<br>daily_cost = df_costs.groupby([pd.Grouper(key=&#39;local_timestamp&#39;, freq=&#39;D&#39;)]).apply(summary_costs).reset_index()<br>daily_cost[&#39;month_cumulated&#39;] = daily_cost.groupby(pd.Grouper(key=&#39;local_timestamp&#39;, freq=&#39;M&#39;))[&#39;total_costs&#39;].cumsum()<br>daily_cost[&#39;day&#39;] = daily_cost[&#39;local_timestamp&#39;].apply(lambda x: x.day)<br>daily_cost[&#39;month&#39;] = daily_cost[&#39;local_timestamp&#39;].apply(lambda x: x.month)<br>daily_plot = daily_cost.pivot_table(index=&#39;day&#39;, columns=&#39;month&#39;, values=&#39;month_cumulated&#39;, aggfunc=&#39;sum&#39;)</pre><p>This is the chart for Accumulated spent by day — Current x Past Month:</p><pre>plt.figure(figsize=(10,10))<br>sns.lineplot(data=daily_plot, legend=True, sizes=(20, 2000))<br>plt.title(&#39;Cumulated spent by day - Current x Past Month&#39;)<br>plt.show()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/831/1*zxhU-yXLiyt3wtRnEBMd7g.png" /><figcaption>Example of Accumulated Spent by day, within a month</figcaption></figure><p>And here we organize the data of the current month to check the consumption by user and model:</p><pre>user_cost = df_costs.loc[df_costs[&#39;local_timestamp&#39;].dt.month==datetime.date.today().month].groupby([&#39;email&#39;], group_keys=False).apply(summary_costs).sort_values(&#39;total_costs&#39;, ascending=False)[[&#39;total_costs&#39;]]<br>snap_cost = df_costs.loc[df_costs[&#39;local_timestamp&#39;].dt.month==datetime.date.today().month].pivot_table(index=&#39;email&#39;, columns=&#39;snapshot_id&#39;, values=&#39;total_costs&#39;, aggfunc=&#39;sum&#39;)<br>user_snap_cost = user_cost.merge(snap_cost, left_index=True, right_index=True, how=&#39;left&#39;)</pre><p>This is the chart for the Total spent by User/Model — Current Month:</p><pre>plt.figure(figsize=(10,10))<br>user_snap_cost.drop(&#39;total_costs&#39;, axis=1).plot(kind=&#39;barh&#39;, stacked=True, color=[&#39;blue&#39;, &#39;red&#39;, &#39;purple&#39;, &#39;orange&#39;, &#39;yellow&#39;, &#39;skyblue&#39;, &#39;green&#39;])<br>plt.gca().invert_yaxis()<br>plt.title(&#39;Total Spent by User/Model - Current Month&#39;)<br>plt.ylabel(&#39;User&#39;)<br>plt.xlabel(&#39;Cost USD&#39;)<br>plt.show()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/554/1*2AlkCIleX84u1dZ8DwyQsQ.png" /></figure><h3>Wrapping up</h3><p>We can use API requests from openai to build our own cost tracking, customizing the way you want to track. In the scripts showed above we are using a local tracking, but you can use this script to build a pipeline (maybe using Airflow) to run this extraction on a daily basis and using the ata to populate any BI tool or fancy dashboard.</p><p>Hope you enjoyed and this could help you keeping track of your OpenAI costs.</p><p>You can find the full code in my github: <a href="https://github.com/bruno-curta/openai-costs-tracking">https://github.com/bruno-curta/openai-costs-tracking</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fb8e2c2dd44" width="1" height="1" alt=""><hr><p><a href="https://medium.com/petlabs/how-to-track-openai-costs-effectively-fb8e2c2dd44">How to track OpenAI costs effectively?</a> was originally published in <a href="https://medium.com/petlabs">Petlabs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>