mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-04-20 14:56:17 -04:00
parent
08d977b8cd
commit
11cfe91ebd
11 changed files with 6721 additions and 8119 deletions
|
@ -286,6 +286,9 @@
|
|||
"watchTriggerable": true,
|
||||
"watchWithFilter": true,
|
||||
"whenever": true,
|
||||
"toValue": true
|
||||
"toValue": true,
|
||||
"injectLocal": true,
|
||||
"provideLocal": true,
|
||||
"useClipboardItems": true
|
||||
}
|
||||
}
|
||||
|
|
9
auto-imports.d.ts
vendored
9
auto-imports.d.ts
vendored
|
@ -36,6 +36,7 @@ declare global {
|
|||
const h: typeof import('vue')['h']
|
||||
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const injectLocal: typeof import('@vueuse/core')['injectLocal']
|
||||
const isDefined: typeof import('@vueuse/core')['isDefined']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
|
@ -65,6 +66,7 @@ declare global {
|
|||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const provideLocal: typeof import('@vueuse/core')['provideLocal']
|
||||
const reactify: typeof import('@vueuse/core')['reactify']
|
||||
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
|
@ -128,6 +130,7 @@ declare global {
|
|||
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
|
||||
const useCached: typeof import('@vueuse/core')['useCached']
|
||||
const useClipboard: typeof import('@vueuse/core')['useClipboard']
|
||||
const useClipboardItems: typeof import('@vueuse/core')['useClipboardItems']
|
||||
const useCloned: typeof import('@vueuse/core')['useCloned']
|
||||
const useColorMode: typeof import('@vueuse/core')['useColorMode']
|
||||
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
|
||||
|
@ -326,6 +329,7 @@ declare module 'vue' {
|
|||
readonly h: UnwrapRef<typeof import('vue')['h']>
|
||||
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
|
||||
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
||||
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
|
||||
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
|
||||
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
|
||||
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
|
||||
|
@ -355,6 +359,7 @@ declare module 'vue' {
|
|||
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
|
||||
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
|
||||
readonly provide: UnwrapRef<typeof import('vue')['provide']>
|
||||
readonly provideLocal: UnwrapRef<typeof import('@vueuse/core')['provideLocal']>
|
||||
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']>
|
||||
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']>
|
||||
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
|
||||
|
@ -418,6 +423,7 @@ declare module 'vue' {
|
|||
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']>
|
||||
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']>
|
||||
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
|
||||
readonly useClipboardItems: UnwrapRef<typeof import('@vueuse/core')['useClipboardItems']>
|
||||
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
|
||||
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
|
||||
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
|
||||
|
@ -610,6 +616,7 @@ declare module '@vue/runtime-core' {
|
|||
readonly h: UnwrapRef<typeof import('vue')['h']>
|
||||
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
|
||||
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
||||
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
|
||||
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
|
||||
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
|
||||
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
|
||||
|
@ -639,6 +646,7 @@ declare module '@vue/runtime-core' {
|
|||
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
|
||||
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
|
||||
readonly provide: UnwrapRef<typeof import('vue')['provide']>
|
||||
readonly provideLocal: UnwrapRef<typeof import('@vueuse/core')['provideLocal']>
|
||||
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']>
|
||||
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']>
|
||||
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
|
||||
|
@ -702,6 +710,7 @@ declare module '@vue/runtime-core' {
|
|||
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']>
|
||||
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']>
|
||||
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
|
||||
readonly useClipboardItems: UnwrapRef<typeof import('@vueuse/core')['useClipboardItems']>
|
||||
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
|
||||
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
|
||||
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
|
||||
|
|
6
components.d.ts
vendored
6
components.d.ts
vendored
|
@ -82,6 +82,7 @@ declare module '@vue/runtime-core' {
|
|||
FormatTransformer: typeof import('./src/components/FormatTransformer.vue')['default']
|
||||
GitMemo: typeof import('./src/tools/git-memo/git-memo.vue')['default']
|
||||
'GitMemo.content': typeof import('./src/tools/git-memo/git-memo.content.md')['default']
|
||||
GptTokenEstimator: typeof import('./src/tools/gpt-token-estimator/gpt-token-estimator.vue')['default']
|
||||
HashText: typeof import('./src/tools/hash-text/hash-text.vue')['default']
|
||||
HmacGenerator: typeof import('./src/tools/hmac-generator/hmac-generator.vue')['default']
|
||||
'Home.page': typeof import('./src/pages/Home.page.vue')['default']
|
||||
|
@ -131,18 +132,19 @@ declare module '@vue/runtime-core' {
|
|||
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
|
||||
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
|
||||
NCheckbox: typeof import('naive-ui')['NCheckbox']
|
||||
NCode: typeof import('naive-ui')['NCode']
|
||||
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
|
||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||
NDivider: typeof import('naive-ui')['NDivider']
|
||||
NEllipsis: typeof import('naive-ui')['NEllipsis']
|
||||
NFormItem: typeof import('naive-ui')['NFormItem']
|
||||
NH1: typeof import('naive-ui')['NH1']
|
||||
NH3: typeof import('naive-ui')['NH3']
|
||||
NIcon: typeof import('naive-ui')['NIcon']
|
||||
NLayout: typeof import('naive-ui')['NLayout']
|
||||
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
|
||||
NMenu: typeof import('naive-ui')['NMenu']
|
||||
NSpace: typeof import('naive-ui')['NSpace']
|
||||
NTable: typeof import('naive-ui')['NTable']
|
||||
NScrollbar: typeof import('naive-ui')['NScrollbar']
|
||||
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
|
||||
OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default']
|
||||
PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default']
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
"figlet": "^1.7.0",
|
||||
"figue": "^1.2.0",
|
||||
"fuse.js": "^6.6.2",
|
||||
"gpt-tokens": "^1.3.13",
|
||||
"highlight.js": "^11.7.0",
|
||||
"iarna-toml-esm": "^3.0.5",
|
||||
"ibantools": "^4.3.3",
|
||||
|
|
14007
pnpm-lock.yaml
generated
14007
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
@ -128,7 +128,7 @@ function activateOption(option: PaletteOption) {
|
|||
<c-input-text ref="inputRef" v-model:value="searchPrompt" raw-text placeholder="Type to search a tool or a command..." autofocus clearable />
|
||||
|
||||
<div v-for="(options, category) in filteredSearchResult" :key="category">
|
||||
<div ml-3 mt-3 text-sm font-bold text-primary op-60>
|
||||
<div ml-3 mt-3 text-sm text-primary font-bold op-60>
|
||||
{{ category }}
|
||||
</div>
|
||||
<command-palette-option v-for="option in options" :key="option.name" :option="option" :selected="selectedOptionIndex === getOptionIndex(option)" @activated="activateOption" />
|
||||
|
|
170
src/tools/gpt-token-estimator/gpt-token-estimator.vue
Normal file
170
src/tools/gpt-token-estimator/gpt-token-estimator.vue
Normal file
|
@ -0,0 +1,170 @@
|
|||
<script setup lang="ts">
|
||||
import { GPTTokens } from 'gpt-tokens';
|
||||
import JSON5 from 'json5';
|
||||
import type { supportModelType } from 'gpt-tokens';
|
||||
import TextareaCopyable from '@/components/TextareaCopyable.vue';
|
||||
import { useValidation } from '@/composable/validation';
|
||||
import { useQueryParamOrStorage } from '@/composable/queryParams';
|
||||
|
||||
const models = GPTTokens.supportModels;
|
||||
|
||||
const model = useQueryParamOrStorage({ name: 'model', storageName: 'gpt-counter:model', defaultValue: 'gpt-3.5-turbo-1106' });
|
||||
const systemPrompt = ref('');
|
||||
const userPrompt = ref('');
|
||||
|
||||
const isAdvancedMode = ref(false);
|
||||
const messagesJsonArray = ref('');
|
||||
const toolsJsonArray = ref('');
|
||||
|
||||
const messagesValidation = useValidation({
|
||||
source: messagesJsonArray,
|
||||
rules: [
|
||||
{
|
||||
message: 'Invalid "messages" array',
|
||||
validator: value => value && JSON5.parse(value.trim()),
|
||||
},
|
||||
],
|
||||
});
|
||||
const toolsValidation = useValidation({
|
||||
source: toolsJsonArray,
|
||||
rules: [
|
||||
{
|
||||
message: 'Invalid "tools" array',
|
||||
validator: value => value && JSON5.parse(value.trim()),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const outputTokenCosts = computed(() => {
|
||||
try {
|
||||
let messagesArray = [];
|
||||
let toolsArray = [];
|
||||
|
||||
if (isAdvancedMode.value) {
|
||||
messagesArray = messagesJsonArray.value ? JSON5.parse(messagesJsonArray.value.trim()) : [];
|
||||
toolsArray = toolsJsonArray.value ? JSON5.parse(toolsJsonArray.value.trim()) : [];
|
||||
}
|
||||
else {
|
||||
if (systemPrompt.value) {
|
||||
messagesArray.push({ role: 'system', content: systemPrompt.value });
|
||||
}
|
||||
if (userPrompt.value) {
|
||||
messagesArray.push({ role: 'user', content: userPrompt.value });
|
||||
}
|
||||
}
|
||||
|
||||
if (!messagesArray.length) {
|
||||
return {
|
||||
error: '',
|
||||
usedTokens: '0',
|
||||
usedUSD: '0',
|
||||
promptUsedTokens: '0',
|
||||
completionUsedTokens: '0',
|
||||
};
|
||||
}
|
||||
|
||||
const tokens = new GPTTokens({
|
||||
model: model.value as supportModelType,
|
||||
messages: messagesArray,
|
||||
tools: toolsArray,
|
||||
});
|
||||
return {
|
||||
error: '',
|
||||
usedTokens: tokens.usedTokens.toString(),
|
||||
usedUSD: tokens.usedUSD.toString(),
|
||||
promptUsedTokens: tokens.promptUsedTokens.toString(),
|
||||
completionUsedTokens: tokens.completionUsedTokens.toString(),
|
||||
};
|
||||
}
|
||||
catch (e: any) {
|
||||
return {
|
||||
error: e.toString(),
|
||||
usedTokens: '',
|
||||
usedUSD: '',
|
||||
promptUsedTokens: '',
|
||||
completionUsedTokens: '',
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<c-select
|
||||
v-model:value="model"
|
||||
label-position="left"
|
||||
label="Model:"
|
||||
:options="models"
|
||||
placeholder="Select GPT model"
|
||||
mb-2
|
||||
/>
|
||||
|
||||
<div flex justify-center>
|
||||
<n-form-item label="Advanded JSON Mode" label-placement="left">
|
||||
<n-checkbox v-model:checked="isAdvancedMode" mr-2 />
|
||||
</n-form-item>
|
||||
</div>
|
||||
|
||||
<c-card v-if="isAdvancedMode" title="Prompts">
|
||||
<c-input-text
|
||||
v-model:value="messagesJsonArray"
|
||||
multiline raw-text
|
||||
placeholder="Your 'messages' JSON array..."
|
||||
rows="5"
|
||||
autofocus
|
||||
label="Your 'messages' JSON array:"
|
||||
:validation="messagesValidation"
|
||||
/>
|
||||
|
||||
<c-input-text
|
||||
v-model:value="toolsJsonArray"
|
||||
multiline raw-text
|
||||
placeholder="Your 'tools' JSON array..."
|
||||
rows="5"
|
||||
autofocus
|
||||
label="Your 'tools' JSON array:"
|
||||
:validation="toolsValidation"
|
||||
/>
|
||||
</c-card>
|
||||
<c-card v-else title="Input JSON(s)">
|
||||
<c-input-text
|
||||
v-model:value="systemPrompt"
|
||||
multiline raw-text
|
||||
placeholder="Your System Prompt content..."
|
||||
rows="2"
|
||||
autofocus
|
||||
label="Your System Prompt content:"
|
||||
/>
|
||||
|
||||
<c-input-text
|
||||
v-model:value="userPrompt"
|
||||
multiline raw-text
|
||||
placeholder="Your User Prompt content..."
|
||||
rows="6"
|
||||
autofocus
|
||||
label="Your User Prompt content:"
|
||||
/>
|
||||
</c-card>
|
||||
|
||||
<n-divider />
|
||||
|
||||
<c-alert v-if="outputTokenCosts.error">
|
||||
{{ outputTokenCosts.error }}
|
||||
</c-alert>
|
||||
|
||||
<div v-if="!outputTokenCosts.error">
|
||||
<n-form-item label="Used Tokens:">
|
||||
<TextareaCopyable :value="outputTokenCosts.usedTokens" />
|
||||
</n-form-item>
|
||||
<n-form-item label="Prompt Tokens:">
|
||||
<TextareaCopyable :value="outputTokenCosts.promptUsedTokens" />
|
||||
</n-form-item>
|
||||
<n-form-item label="Completion Tokens:">
|
||||
<TextareaCopyable :value="outputTokenCosts.completionUsedTokens" />
|
||||
</n-form-item>
|
||||
<n-form-item label="Used USD:">
|
||||
<TextareaCopyable :value="outputTokenCosts.usedUSD" />
|
||||
</n-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
12
src/tools/gpt-token-estimator/index.ts
Normal file
12
src/tools/gpt-token-estimator/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { CurrencyDollar } from '@vicons/tabler';
|
||||
import { defineTool } from '../tool';
|
||||
|
||||
export const tool = defineTool({
|
||||
name: 'GPT Token Estimator',
|
||||
path: '/gpt-token-estimator',
|
||||
description: 'OpenAI GPT Token Estimator',
|
||||
keywords: ['gpt', 'token', 'estimator'],
|
||||
component: () => import('./gpt-token-estimator.vue'),
|
||||
icon: CurrencyDollar,
|
||||
createdAt: new Date('2024-08-15'),
|
||||
});
|
|
@ -2,6 +2,7 @@ import { tool as base64FileConverter } from './base64-file-converter';
|
|||
import { tool as base64StringConverter } from './base64-string-converter';
|
||||
import { tool as basicAuthGenerator } from './basic-auth-generator';
|
||||
import { tool as emailNormalizer } from './email-normalizer';
|
||||
import { tool as gptTokenEstimator } from './gpt-token-estimator';
|
||||
|
||||
import { tool as asciiTextDrawer } from './ascii-text-drawer';
|
||||
|
||||
|
@ -160,6 +161,7 @@ export const toolsByCategory: ToolCategory[] = [
|
|||
emailNormalizer,
|
||||
regexTester,
|
||||
regexMemo,
|
||||
gptTokenEstimator,
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
@ -151,7 +151,7 @@ function onSearchInput() {
|
|||
>
|
||||
<div flex-1 truncate>
|
||||
<slot name="displayed-value">
|
||||
<input v-if="searchable && isOpen" ref="searchInputRef" v-model="searchQuery" type="text" placeholder="Search..." class="search-input" w-full lh-normal color-current @input="onSearchInput">
|
||||
<input v-if="searchable && isOpen" ref="searchInputRef" v-model="searchQuery" type="text" placeholder="Search..." class="search-input" w-full color-current lh-normal @input="onSearchInput">
|
||||
<span v-else-if="selectedOption" lh-normal>
|
||||
{{ selectedOption.label }}
|
||||
</span>
|
||||
|
|
|
@ -39,7 +39,7 @@ const headers = computed(() => {
|
|||
<template>
|
||||
<div class="relative overflow-x-auto rounded">
|
||||
<table class="w-full border-collapse text-left text-sm text-gray-500 dark:text-gray-400" role="table" :aria-label="description">
|
||||
<thead v-if="!hideHeaders" class="bg-#ffffff uppercase text-gray-700 dark:bg-#333333 dark:text-gray-400" border-b="1px solid dark:transparent #efeff5">
|
||||
<thead v-if="!hideHeaders" class="bg-#ffffff text-gray-700 uppercase dark:bg-#333333 dark:text-gray-400" border-b="1px solid dark:transparent #efeff5">
|
||||
<tr>
|
||||
<th v-for="header in headers" :key="header.key" scope="col" class="px-6 py-3 text-xs">
|
||||
{{ header.label }}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue