├── .github
├── dependabot.yml
└── workflows
│ ├── build-frontend.yml
│ ├── build.yml
│ ├── docker-frontend.yaml
│ ├── docker.yaml
│ └── release.yaml
├── .gitignore
├── CHANGELOG.md
├── CNAME
├── Dockerfile
├── LICENSE
├── README.md
├── _fixtures
└── testing
│ ├── .gitignore
│ ├── requirements.txt
│ └── st.py
├── build.gradle.kts
├── choc-ui
├── .editorconfig
├── .env.example
├── .eslintrc.json
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── __tests__
│ └── dsl-parse.test.js
├── app
│ ├── editor
│ │ └── page.tsx
│ ├── globals.css
│ ├── layout.tsx
│ └── page.tsx
├── assets
│ └── fonts
│ │ ├── Inter-Bold.woff
│ │ └── Inter-Regular.woff
├── components
│ ├── button-scroll-to-bottom.tsx
│ ├── chat-list.tsx
│ ├── chat-message-actions.tsx
│ ├── chat-message.tsx
│ ├── chat-panel.tsx
│ ├── chat-scroll-anchor.tsx
│ ├── chat.tsx
│ ├── clear-history.tsx
│ ├── dsl
│ │ ├── design-block.tsx
│ │ ├── design-dsl-render.tsx
│ │ └── design-dsl.ts
│ ├── editor
│ │ ├── live-editor.tsx
│ │ └── styles.css
│ ├── empty-screen.tsx
│ ├── external-link.tsx
│ ├── flow
│ │ ├── types.ts
│ │ ├── use-chat.ts
│ │ └── utils.ts
│ ├── footer.tsx
│ ├── header.tsx
│ ├── interpreter
│ │ ├── iframe.tsx
│ │ └── message.ts
│ ├── markdown.tsx
│ ├── prompt-form.tsx
│ ├── providers.tsx
│ ├── sidebar-actions.tsx
│ ├── sidebar-footer.tsx
│ ├── sidebar-item.tsx
│ ├── sidebar.tsx
│ ├── tailwind-indicator.tsx
│ ├── theme-toggle.tsx
│ ├── toaster.tsx
│ ├── ui
│ │ ├── alert-dialog.tsx
│ │ ├── badge.tsx
│ │ ├── button.tsx
│ │ ├── codeblock.tsx
│ │ ├── dialog.tsx
│ │ ├── dropdown-menu.tsx
│ │ ├── icons.tsx
│ │ ├── input.tsx
│ │ ├── label.tsx
│ │ ├── select.tsx
│ │ ├── separator.tsx
│ │ ├── sheet.tsx
│ │ ├── switch.tsx
│ │ ├── textarea.tsx
│ │ └── tooltip.tsx
│ └── workflow
│ │ ├── domains.tsx
│ │ ├── prompt-example.ts
│ │ ├── stage.ts
│ │ ├── workflow-dto.ts
│ │ └── workflow.ts
├── docs
│ └── test-case-1.md
├── jest.config.js
├── jest.setup.js
├── lib
│ ├── analytics.ts
│ ├── fonts.ts
│ ├── hooks
│ │ ├── use-at-bottom.tsx
│ │ ├── use-copy-to-clipboard.tsx
│ │ ├── use-enter-submit.tsx
│ │ └── use-local-storage.ts
│ ├── types.ts
│ └── utils.ts
├── next-env.d.ts
├── next.config.js
├── package.json
├── pnpm-lock.yaml
├── postcss.config.js
├── prettier.config.cjs
├── public
│ ├── favicon-16x16.png
│ ├── next.svg
│ ├── thirteen.svg
│ └── vercel.svg
├── tailwind.config.js
└── tsconfig.json
├── cocoa-core
├── README.md
├── build.gradle.kts
└── src
│ ├── main
│ └── kotlin
│ │ └── cc
│ │ └── unitmesh
│ │ ├── agent
│ │ └── Tool.kt
│ │ ├── cf
│ │ └── core
│ │ │ ├── Domain.kt
│ │ │ ├── cache
│ │ │ └── CachableEmbedding.kt
│ │ │ ├── context
│ │ │ ├── DslContext.kt
│ │ │ ├── DslContextBuilder.kt
│ │ │ └── variable
│ │ │ │ ├── Variable.kt
│ │ │ │ └── VariableResolver.kt
│ │ │ ├── dsl
│ │ │ ├── Dsl.kt
│ │ │ ├── DslCompiler.kt
│ │ │ ├── DslInterpreter.kt
│ │ │ ├── IndexElement.kt
│ │ │ ├── Interpreter.kt
│ │ │ └── InterpreterContext.kt
│ │ │ ├── flow
│ │ │ ├── DomainDeclaration.kt
│ │ │ ├── ProblemAnalyzer.kt
│ │ │ ├── ProblemClarifier.kt
│ │ │ ├── SolutionDesigner.kt
│ │ │ ├── SolutionExecutor.kt
│ │ │ ├── SolutionReviewer.kt
│ │ │ ├── Workflow.kt
│ │ │ ├── model
│ │ │ │ ├── Answer.kt
│ │ │ │ ├── ChatWebContext.kt
│ │ │ │ ├── FlowActionFlag.kt
│ │ │ │ ├── StageContext.kt
│ │ │ │ └── WorkflowResult.kt
│ │ │ └── related
│ │ │ │ └── RelatedQueryService.kt
│ │ │ ├── llms
│ │ │ ├── ChatMessage.kt
│ │ │ ├── LlmProvider.kt
│ │ │ ├── MockLlmProvider.kt
│ │ │ └── TemperatureMode.kt
│ │ │ ├── parser
│ │ │ └── MarkdownCode.kt
│ │ │ ├── prompt
│ │ │ ├── PromptExample.kt
│ │ │ ├── QAExample.kt
│ │ │ ├── ReActPrompt.kt
│ │ │ ├── StringTemplate.kt
│ │ │ └── UpdatableExample.kt
│ │ │ └── utils
│ │ │ ├── Constants.kt
│ │ │ └── IdUtil.kt
│ │ ├── docs
│ │ └── Document.kt
│ │ ├── nlp
│ │ ├── embedding
│ │ │ ├── Embedding.kt
│ │ │ ├── EmbeddingElement.kt
│ │ │ ├── EmbeddingProvider.kt
│ │ │ ├── EncodingTokenizer.kt
│ │ │ ├── OpenAiEncoding.kt
│ │ │ └── text
│ │ │ │ └── EnglishTextEmbeddingProvider.kt
│ │ ├── search
│ │ │ └── TfIdf.kt
│ │ ├── similarity
│ │ │ ├── CosineSimilarity.kt
│ │ │ ├── JaccardSimilarity.kt
│ │ │ ├── RelevanceScore.kt
│ │ │ ├── Similarity.kt
│ │ │ └── SimilarityScore.kt
│ │ └── tokenizer
│ │ │ ├── CodeNamingTokenizer.kt
│ │ │ ├── SplittingRegExpTokenizer.kt
│ │ │ ├── Tokenizer.kt
│ │ │ ├── WordTokenizer.kt
│ │ │ └── regexp
│ │ │ ├── RegexTokenizerOptions.kt
│ │ │ └── RegexpTokenizer.kt
│ │ ├── rag
│ │ ├── document
│ │ │ ├── Document.kt
│ │ │ ├── DocumentOrder.kt
│ │ │ ├── DocumentParser.kt
│ │ │ ├── DocumentType.kt
│ │ │ └── Metadata.kt
│ │ ├── loader
│ │ │ ├── JsonLoader.kt
│ │ │ └── Loader.kt
│ │ ├── memory
│ │ │ └── Memory.kt
│ │ ├── retriever
│ │ │ ├── EmbeddingStoreRetriever.kt
│ │ │ └── Retriever.kt
│ │ ├── splitter
│ │ │ ├── CharacterTextSplitter.kt
│ │ │ ├── MarkdownHeaderTextSplitter.kt
│ │ │ ├── Splitter.kt
│ │ │ ├── TextSplitter.kt
│ │ │ └── TokenTextSplitter.kt
│ │ └── store
│ │ │ ├── EmbeddingMatch.kt
│ │ │ ├── EmbeddingStore.kt
│ │ │ ├── InMemoryEmbeddingStore.kt
│ │ │ └── InMemoryEnglishTextStore.kt
│ │ └── template
│ │ ├── PromptCompiler.kt
│ │ ├── TemplateEngineType.kt
│ │ ├── TemplateRoleSplitter.kt
│ │ └── VelocityCompiler.kt
│ └── test
│ └── kotlin
│ └── cc
│ └── unitmesh
│ ├── cf
│ └── core
│ │ ├── flow
│ │ └── model
│ │ │ └── FlowActionFlagTest.kt
│ │ └── parser
│ │ └── MarkdownCodeTest.kt
│ ├── nlp
│ ├── similarity
│ │ ├── CosineSimilarityTest.kt
│ │ └── JaccardSimilarityTest.kt
│ └── tokenizer
│ │ └── SplittingRegExpTokenizerTest.kt
│ └── rag
│ ├── document
│ └── DocumentOrderTest.kt
│ ├── splitter
│ ├── CharacterTextSplitterTest.kt
│ └── MarkdownHeaderTextSplitterTest.kt
│ └── store
│ ├── InMemoryEmbeddingStoreTest.kt
│ └── InMemoryEnglishTextStoreTest.kt
├── code-modules
├── README.md
├── api-tool-parser
│ ├── .gitignore
│ ├── README.md
│ ├── build.gradle.kts
│ └── src
│ │ ├── main
│ │ ├── kotlin
│ │ │ └── cc
│ │ │ │ └── unitmesh
│ │ │ │ └── processor
│ │ │ │ └── api
│ │ │ │ └── ApiProcessorDetector.kt
│ │ └── resources
│ │ │ ├── logback-test.xml
│ │ │ └── logback.xml
│ │ └── test
│ │ ├── kotlin
│ │ └── cc
│ │ │ └── unitmesh
│ │ │ └── processor
│ │ │ └── api
│ │ │ └── ApiProcessorDetectorTest.kt
│ │ └── resources
│ │ ├── openapi
│ │ ├── Box.json
│ │ └── CircleCI.postman_collection.json
│ │ ├── postman
│ │ └── Wechat-Simple.postman_collection.json
│ │ └── testsets
│ │ ├── postman.json
│ │ ├── swagger-3.json
│ │ └── swagger-3.yaml
├── code-language
│ ├── build.gradle.kts
│ └── src
│ │ ├── main
│ │ ├── kotlin
│ │ │ └── cc
│ │ │ │ └── unitmesh
│ │ │ │ └── language
│ │ │ │ ├── Language.kt
│ │ │ │ ├── LanguageService.kt
│ │ │ │ └── Trie.kt
│ │ └── resources
│ │ │ └── languages.json
│ │ └── test
│ │ └── kotlin
│ │ └── cc
│ │ └── unitmesh
│ │ └── language
│ │ ├── LanguageServiceTest.kt
│ │ └── TrieTest.kt
├── code-splitter
│ ├── LICENSE
│ ├── README.md
│ ├── build.gradle.kts
│ └── src
│ │ ├── main
│ │ └── kotlin
│ │ │ └── cc
│ │ │ └── unitmesh
│ │ │ └── cf
│ │ │ └── code
│ │ │ └── CodeSplitter.kt
│ │ └── test
│ │ └── kotlin
│ │ └── cc
│ │ └── unitmesh
│ │ └── cf
│ │ └── code
│ │ └── CodeSplitterTest.kt
├── git-commit-message
│ ├── README.md
│ ├── build.gradle.kts
│ ├── docs
│ │ └── conventional.js
│ └── src
│ │ ├── main
│ │ └── kotlin
│ │ │ └── org
│ │ │ └── changelog
│ │ │ ├── CommitBase.kt
│ │ │ ├── CommitParser.kt
│ │ │ ├── LICENSE.md
│ │ │ ├── ParserOptions.kt
│ │ │ ├── ParserRegexes.kt
│ │ │ └── RegexParser.kt
│ │ └── test
│ │ ├── kotlin
│ │ └── org
│ │ │ └── changelog
│ │ │ ├── CommentMentionsCommitParserTest.kt
│ │ │ ├── CommitParserTest.kt
│ │ │ ├── FooterCommitParserTest.kt
│ │ │ └── RegexParserTest.kt
│ │ └── resources
│ │ └── commits
│ │ ├── allows-for-multiple-newlines-between-summary-and-body.json
│ │ ├── parses-commit-summary-footer.json
│ │ ├── parses-summary-with-multiple-spaces-after-separator.json
│ │ ├── parses-summary-with-no-scope.json
│ │ ├── parses-summary-with-scope.json
│ │ └── supports-multiline-breaking-changes-via-continuation.json
└── git-differ
│ ├── build.gradle.kts
│ └── src
│ ├── main
│ └── kotlin
│ │ └── cc
│ │ └── unitmesh
│ │ └── cf
│ │ └── code
│ │ ├── ChangedLineCount.kt
│ │ ├── ChangedNode.kt
│ │ ├── GitCommand.kt
│ │ ├── GitDiffer.kt
│ │ ├── OptimizePatch.kt
│ │ └── command
│ │ ├── Command.kt
│ │ ├── ExecListeners.kt
│ │ └── OS.kt
│ └── test
│ ├── kotlin
│ └── cc
│ │ └── unitmesh
│ │ └── cf
│ │ └── code
│ │ ├── GitCommandTest.kt
│ │ ├── GitDifferTest.kt
│ │ └── command
│ │ └── CommandTest.kt
│ └── resources
│ └── logback.xml
├── docker-compose.yml
├── docs-builder
├── README.md
├── build.gradle.kts
└── src
│ ├── main
│ └── kotlin
│ │ ├── cc
│ │ └── unitmesh
│ │ │ └── docs
│ │ │ ├── KDocGen.kt
│ │ │ ├── Runner.kt
│ │ │ ├── kdoc
│ │ │ └── findKDoc.kt
│ │ │ ├── model
│ │ │ ├── DocContent.kt
│ │ │ ├── DocGenerator.kt
│ │ │ └── RootDocContent.kt
│ │ │ ├── render
│ │ │ └── Render.kt
│ │ │ └── sample
│ │ │ ├── ClassSample.kt
│ │ │ └── FunctionSample.kt
│ │ └── com
│ │ └── pinterest
│ │ └── ktlint
│ │ ├── Code.kt
│ │ ├── FileUtils.kt
│ │ └── KtFileProcessor.kt
│ └── test
│ └── kotlin
│ └── cc
│ └── unitmesh
│ └── docs
│ ├── KDocGenTest.kt
│ └── RunnerTest.kt
├── docs
├── CNAME
├── _config.yml
├── architecture.svg
├── dsl
│ ├── design.md
│ ├── dsl.md
│ └── semantic-dsl.md
├── evaluation
│ ├── evaluation.md
│ └── github-copilot.md
├── faq.md
├── favicon.ico
├── home.md
├── images
│ └── chocolate-factory.svg
├── logo.svg
├── modules
│ ├── code-splitter.md
│ ├── interpreter.md
│ ├── local-embedding.md
│ └── modules.md
├── patterns
│ ├── coordinate-model.md
│ ├── flare.md
│ ├── hyde.md
│ ├── light-weight-llm.md
│ ├── long-context-reorder.md
│ ├── patterns.md
│ ├── pre-built-embedding.md
│ └── query-to-doc.md
├── prompt-script
│ ├── connection-config.md
│ ├── job-strategy.md
│ ├── prompt-script.md
│ ├── template-datasource.md
│ └── validate-rule.md
├── prompt
│ ├── frontend
│ │ ├── frontend-clarify.md
│ │ ├── frontend-design.md
│ │ ├── frontend-execute.md
│ │ └── frontend-overview.md
│ ├── prompt.md
│ ├── qa
│ │ ├── qa-clarify.md
│ │ └── qa-design.md
│ └── semantic
│ │ ├── compare.md
│ │ ├── semantic-analysis.md
│ │ ├── semantic-execute.md
│ │ └── semantic-overview.md
├── rag-script
│ ├── prompt-text.md
│ ├── rag-script.md
│ └── workflow.md
├── rag
│ ├── data-manage.md
│ ├── document.md
│ ├── embedding-model.md
│ ├── rag.md
│ ├── splitter.md
│ └── vector-store.md
├── resources.md
├── setup.md
└── workflow
│ ├── semantic-code-search.md
│ ├── workflow-development.md
│ └── workflow.md
├── dsl
└── design
│ ├── README.md
│ ├── build.gradle.kts
│ └── src
│ ├── main
│ ├── antlr
│ │ └── Design.g4
│ └── kotlin
│ │ └── cc
│ │ └── unitmesh
│ │ └── dsl
│ │ └── design
│ │ ├── DesignAppListener.kt
│ │ ├── DesignDsl.kt
│ │ └── DesignModel.kt
│ └── test
│ └── kotlin
│ └── cc
│ └── unitmesh
│ └── dsl
│ └── design
│ └── DesignDslTest.kt
├── examples
├── prompt-script
│ ├── .gitignore
│ ├── code-complete.open-ai.vm
│ ├── connection.yml
│ ├── datasource.json
│ └── prompt.unit-mesh.yml
└── rag-script
│ ├── code-semantic.main.kts
│ ├── english-text.main.kts
│ ├── filename.txt
│ └── sentence-transformers.main.kts
├── gradle
├── libs.versions.toml
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── llm-modules
├── connection
│ ├── README.md
│ ├── build.gradle.kts
│ └── src
│ │ ├── main
│ │ └── kotlin
│ │ │ └── cc
│ │ │ └── unitmesh
│ │ │ └── connection
│ │ │ ├── ConnectionConfig.kt
│ │ │ ├── MockLlmConnection.kt
│ │ │ └── OpenAiConnection.kt
│ │ └── test
│ │ └── resources
│ │ ├── connection
│ │ ├── azure_openai.yml
│ │ ├── custom.yml
│ │ ├── openai.yml
│ │ └── serp.yml
│ │ └── schemas
│ │ ├── AzureOpenAIConnection.schema.json
│ │ ├── CustomConnection.schema.json
│ │ ├── OpenAIConnection.schema.json
│ │ └── SerpConnection.schema.json
├── dan-bert-tiny
│ ├── build.gradle.kts
│ └── src
│ │ └── main
│ │ └── resources
│ │ ├── bert-base-uncased.txt
│ │ ├── dan_optimized_fp16.onnx
│ │ └── tokenizer_config.json
├── local-embedding
│ ├── README.md
│ ├── build.gradle.kts
│ └── src
│ │ ├── main
│ │ ├── kotlin
│ │ │ └── cc
│ │ │ │ └── unitmesh
│ │ │ │ └── cf
│ │ │ │ ├── Embedding.kt
│ │ │ │ └── LocalEmbedding.kt
│ │ └── resources
│ │ │ └── model
│ │ │ ├── LICENSE
│ │ │ ├── model.onnx
│ │ │ ├── special_tokens_map.json
│ │ │ ├── tokenizer.json
│ │ │ ├── tokenizer_config.json
│ │ │ └── vocab.txt
│ │ └── test
│ │ └── kotlin
│ │ └── cc
│ │ └── unitmesh
│ │ └── cf
│ │ ├── DanBertTest.kt
│ │ └── STSemanticTest.kt
├── openai
│ ├── build.gradle.kts
│ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── cc
│ │ └── unitmesh
│ │ ├── azure
│ │ ├── AzureOpenAIDto.kt
│ │ ├── AzureOpenAiProvider.kt
│ │ └── ResponseBodyCallback.kt
│ │ └── openai
│ │ ├── MsgConverter.kt
│ │ ├── OpenAiEmbeddingProvider.kt
│ │ └── OpenAiProvider.kt
└── prompt-script
│ ├── README.md
│ ├── build.gradle.kts
│ └── src
│ ├── main
│ ├── kotlin
│ │ └── cc
│ │ │ └── unitmesh
│ │ │ └── prompt
│ │ │ ├── Main.kt
│ │ │ ├── PromptScriptCommand.kt
│ │ │ ├── executor
│ │ │ ├── ScriptExecutor.kt
│ │ │ ├── base
│ │ │ │ ├── JobStrategyExecutor.kt
│ │ │ │ └── SingleJobExecuteStrategy.kt
│ │ │ └── strategy
│ │ │ │ ├── ConnectionExecuteStrategy.kt
│ │ │ │ ├── DatasourceCollectionStrategy.kt
│ │ │ │ └── RepeatExecuteStrategy.kt
│ │ │ ├── model
│ │ │ ├── Job.kt
│ │ │ ├── JobStrategy.kt
│ │ │ ├── PromptScript.kt
│ │ │ ├── TemplateDatasource.kt
│ │ │ ├── ValidateRule.kt
│ │ │ └── Variable.kt
│ │ │ ├── template
│ │ │ └── TemplateDataCompile.kt
│ │ │ └── validate
│ │ │ ├── CodeCompletionValidator.kt
│ │ │ ├── ExtToolValidator.kt
│ │ │ ├── JsonPathValidator.kt
│ │ │ ├── JsonValidator.kt
│ │ │ ├── MarkdownCodeBlockValidator.kt
│ │ │ ├── RegexValidator.kt
│ │ │ ├── StringValidator.kt
│ │ │ └── Validator.kt
│ └── resources
│ │ └── logback.xml
│ └── test
│ ├── kotlin
│ └── cc
│ │ └── unitmesh
│ │ └── prompt
│ │ ├── PromptManagerTest.kt
│ │ ├── PromptScriptCommandTest.kt
│ │ ├── executor
│ │ ├── ScriptExecutorTest.kt
│ │ └── TemplateRoleSplitterTest.kt
│ │ ├── model
│ │ ├── JobTest.kt
│ │ ├── PromptScriptTest.kt
│ │ ├── ValidateRuleTest.kt
│ │ └── VariableTest.kt
│ │ └── validate
│ │ ├── CodeCompletionValidatorTest.kt
│ │ ├── ExtToolValidatorTest.kt
│ │ ├── JsonPathValidatorTest.kt
│ │ ├── JsonValidatorTest.kt
│ │ ├── MarkdownCodeBlockValidatorTest.kt
│ │ ├── RegexValidatorTest.kt
│ │ └── StringValidatorTest.kt
│ └── resources
│ ├── connection
│ └── prompt-connection.yml
│ ├── flow
│ ├── Flow.schema.json
│ └── flow.dag.yaml
│ ├── prompt.unit-mesh.yml
│ └── testdata
│ ├── sample.json
│ └── ui-clarify.open_ai.vm
├── llm-tools
├── interpreter
│ ├── .gitignore
│ ├── build.gradle.kts
│ └── src
│ │ ├── main
│ │ └── kotlin
│ │ │ └── cc
│ │ │ └── unitmesh
│ │ │ └── code
│ │ │ ├── interpreter
│ │ │ ├── KotlinInterpreter.kt
│ │ │ ├── api
│ │ │ │ └── InterpreterRequest.kt
│ │ │ └── compiler
│ │ │ │ ├── CustomLibraryResolver.kt
│ │ │ │ ├── ExtendLibraries.kt
│ │ │ │ ├── KotlinReplWrapper.kt
│ │ │ │ └── SimpleLibraryDefinition.kt
│ │ │ ├── magic
│ │ │ ├── LangCodeWrapper.kt
│ │ │ ├── SimpleMagicMatcher.kt
│ │ │ └── lang
│ │ │ │ ├── KtorLangBuilder.kt
│ │ │ │ ├── LangBuilder.kt
│ │ │ │ └── SpringLangBuilder.kt
│ │ │ └── messaging
│ │ │ ├── Message.kt
│ │ │ └── MessageType.kt
│ │ └── test
│ │ └── kotlin
│ │ └── cc
│ │ └── unitmesh
│ │ └── code
│ │ └── interpreter
│ │ ├── KotlinInterpreterTest.kt
│ │ ├── KotlinReplWrapperTest.kt
│ │ └── LetsPlotInterpreterTest.kt
└── web-tools
│ ├── build.gradle.kts
│ └── src
│ ├── main
│ └── kotlin
│ │ └── cc
│ │ └── unitmesh
│ │ └── tools
│ │ └── web
│ │ └── Wikimedia.kt
│ └── test
│ └── kotlin
│ └── cc
│ └── unitmesh
│ └── tools
│ └── web
│ └── WikimediaTest.kt
├── nginx
├── Dockerfile
└── default.conf
├── packages
├── .gitignore
└── ui-components-parser
│ ├── .gitignore
│ ├── README.md
│ ├── mui
│ ├── docs-parser.js
│ └── mui-parser.js
│ ├── package.json
│ └── pnpm-lock.yaml
├── rag-modules
├── document
│ ├── build.gradle.kts
│ └── src
│ │ ├── main
│ │ └── kotlin
│ │ │ └── cc
│ │ │ └── unitmesh
│ │ │ └── document
│ │ │ ├── DocumentFactory.kt
│ │ │ └── parser
│ │ │ ├── MdDocumentParser.kt
│ │ │ ├── MsOfficeDocumentParser.kt
│ │ │ ├── PdfDocumentParser.kt
│ │ │ └── TextDocumentParser.kt
│ │ └── test
│ │ ├── kotlin
│ │ └── cc
│ │ │ └── unitmesh
│ │ │ └── document
│ │ │ └── parser
│ │ │ ├── MdDocumentParserTest.kt
│ │ │ └── MsOfficeDocumentParserTest.kt
│ │ └── resources
│ │ ├── ChocolateFactory.docx
│ │ └── sample.pptx
├── rag-script
│ ├── .gitignore
│ ├── README.md
│ ├── build.gradle.kts
│ ├── docs
│ │ └── metric.md
│ └── src
│ │ ├── main
│ │ └── kotlin
│ │ │ └── cc
│ │ │ └── unitmesh
│ │ │ └── rag
│ │ │ ├── CodeDsl.kt
│ │ │ ├── DocumentDsl.kt
│ │ │ ├── EmbeddingEngine.kt
│ │ │ ├── Exec.kt
│ │ │ ├── HttpDsl.kt
│ │ │ ├── LlmConnector.kt
│ │ │ ├── PromptText.kt
│ │ │ ├── Rag.kt
│ │ │ ├── Store.kt
│ │ │ ├── Text.kt
│ │ │ └── base
│ │ │ └── RagScript.kt
│ │ └── test
│ │ └── kotlin
│ │ └── cc
│ │ └── unitmesh
│ │ └── rag
│ │ ├── PromptTextTest.kt
│ │ └── WorkflowTest.kt
├── store-elasticsearch
│ ├── build.gradle.kts
│ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── cc
│ │ └── unitmesh
│ │ └── store
│ │ ├── ElasticsearchRequestFailedException.kt
│ │ └── ElasticsearchStore.kt
├── store-milvus
│ ├── build.gradle.kts
│ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── cc
│ │ └── unitmesh
│ │ └── store
│ │ └── MilvusEmbeddingStore.kt
└── store-pinecone
│ ├── build.gradle.kts
│ └── src
│ └── main
│ └── kotlin
│ └── cc
│ └── unitmesh
│ └── store
│ └── PineconeEmbeddingStore.kt
├── server
├── build.gradle.kts
├── elastic-search.http
├── src
│ ├── main
│ │ ├── kotlin
│ │ │ └── cc
│ │ │ │ └── unitmesh
│ │ │ │ └── cf
│ │ │ │ ├── ChocolateFactoryApplication.kt
│ │ │ │ ├── domains
│ │ │ │ ├── DomainClassify.kt
│ │ │ │ ├── SupportedDomains.kt
│ │ │ │ ├── frontend
│ │ │ │ │ ├── FEDomainDecl.kt
│ │ │ │ │ ├── FEWorkflow.kt
│ │ │ │ │ ├── context
│ │ │ │ │ │ ├── FEContext.kt
│ │ │ │ │ │ ├── FEDslContextBuilder.kt
│ │ │ │ │ │ ├── FEVariableResolver.kt
│ │ │ │ │ │ └── FEVariables.kt
│ │ │ │ │ ├── flow
│ │ │ │ │ │ ├── FEProblemClarifier.kt
│ │ │ │ │ │ ├── FESolutionDesigner.kt
│ │ │ │ │ │ └── FESolutionExecutor.kt
│ │ │ │ │ └── model
│ │ │ │ │ │ ├── AtomicElement.kt
│ │ │ │ │ │ ├── UiComponent.kt
│ │ │ │ │ │ └── UiPage.kt
│ │ │ │ ├── interpreter
│ │ │ │ │ ├── CodeInterpreter.kt
│ │ │ │ │ ├── CodeInterpreterDomainDecl.kt
│ │ │ │ │ ├── CodeInterpreterWorkflow.kt
│ │ │ │ │ └── flow
│ │ │ │ │ │ └── CodeSolutionExecutor.kt
│ │ │ │ ├── semantic
│ │ │ │ │ ├── CodeSemanticDecl.kt
│ │ │ │ │ ├── CodeSemanticWorkflow.kt
│ │ │ │ │ ├── context
│ │ │ │ │ │ ├── SemanticVariableResolver.kt
│ │ │ │ │ │ └── SemanticVariables.kt
│ │ │ │ │ ├── flow
│ │ │ │ │ │ ├── SemanticProblemAnalyzer.kt
│ │ │ │ │ │ └── SemanticSolutionExecutor.kt
│ │ │ │ │ └── model
│ │ │ │ │ │ └── ExplainQuery.kt
│ │ │ │ ├── spec
│ │ │ │ │ ├── SpecDomainDecl.kt
│ │ │ │ │ ├── SpecRelevantSearch.kt
│ │ │ │ │ ├── SpecWorkflow.kt
│ │ │ │ │ └── flow
│ │ │ │ │ │ └── SpecSolutionExecutor.kt
│ │ │ │ ├── sql
│ │ │ │ │ ├── SqlWorkflow.kt
│ │ │ │ │ └── domain
│ │ │ │ │ │ └── SqlDsl.kt
│ │ │ │ └── testcase
│ │ │ │ │ ├── TestcaseDomainDecl.kt
│ │ │ │ │ ├── TestcaseWorkflow.kt
│ │ │ │ │ ├── context
│ │ │ │ │ ├── TestcaseVariableResolver.kt
│ │ │ │ │ └── TestcaseVariables.kt
│ │ │ │ │ ├── flow
│ │ │ │ │ ├── TestcaseProblemAnalyzer.kt
│ │ │ │ │ ├── TestcaseSolutionDesigner.kt
│ │ │ │ │ └── TestcaseSolutionReviewer.kt
│ │ │ │ │ └── model
│ │ │ │ │ └── TestcasePrinciples.kt
│ │ │ │ ├── infrastructure
│ │ │ │ ├── cache
│ │ │ │ │ ├── CachedEmbeddingService.kt
│ │ │ │ │ ├── EmbeddingCache.kt
│ │ │ │ │ └── utils
│ │ │ │ │ │ └── EmbeddingConverter.kt
│ │ │ │ ├── llms
│ │ │ │ │ ├── LlmProviderFactory.kt
│ │ │ │ │ ├── completion
│ │ │ │ │ │ ├── MockLlmProvider.kt
│ │ │ │ │ │ ├── OpenAiCompletionService.kt
│ │ │ │ │ │ └── model
│ │ │ │ │ │ │ └── SimpleOpenAIFormat.kt
│ │ │ │ │ ├── configuration
│ │ │ │ │ │ └── OpenAiConfiguration.kt
│ │ │ │ │ └── embedding
│ │ │ │ │ │ ├── OpenAiEmbeddingService.kt
│ │ │ │ │ │ └── SentenceTransformersEmbedding.kt
│ │ │ │ └── repository
│ │ │ │ │ └── EmbeddingCacheRepository.kt
│ │ │ │ └── presentation
│ │ │ │ ├── AgentController.kt
│ │ │ │ ├── ArchGuardScanController.kt
│ │ │ │ ├── ChatController.kt
│ │ │ │ ├── CodeDocumentController.kt
│ │ │ │ ├── DslController.kt
│ │ │ │ ├── WorkflowController.kt
│ │ │ │ ├── config
│ │ │ │ └── WebConfig.kt
│ │ │ │ └── dto
│ │ │ │ └── DomainResponse.kt
│ │ └── resources
│ │ │ ├── application.yml
│ │ │ ├── be
│ │ │ └── specification.md
│ │ │ └── frontend
│ │ │ ├── components
│ │ │ └── mui-mini.json
│ │ │ └── layouts
│ │ │ └── layout-style.json
│ └── test
│ │ ├── kotlin
│ │ ├── RagIntegrationTests.kt
│ │ └── cc
│ │ │ └── unitmesh
│ │ │ └── cf
│ │ │ ├── ChocolateFactoryApplicationTests.kt
│ │ │ ├── domains
│ │ │ ├── DomainClassifyTest.kt
│ │ │ ├── frontend
│ │ │ │ ├── context
│ │ │ │ │ └── FEVariableResolverTest.kt
│ │ │ │ ├── model
│ │ │ │ │ └── UiPageTest.kt
│ │ │ │ └── prompt
│ │ │ │ │ └── FEWorkflowTestController.kt
│ │ │ ├── interpreter
│ │ │ │ └── CodeInterpreterWorkflowTest.kt
│ │ │ ├── semantic
│ │ │ │ ├── CodeSemanticWorkflowTest.kt
│ │ │ │ └── model
│ │ │ │ │ └── ExplainQueryTest.kt
│ │ │ └── testcase
│ │ │ │ └── TestcaseWorkflowTest.kt
│ │ │ ├── infrastructure
│ │ │ └── llms
│ │ │ │ └── completion
│ │ │ │ └── OpenAiCompletionServiceTest.kt
│ │ │ └── presentation
│ │ │ └── DslControllerTest.kt
│ │ └── resources
│ │ ├── application.yml
│ │ └── rag
│ │ ├── be.md
│ │ └── bikes.json
└── workflow-testing.http
└── settings.gradle.kts
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # Dependabot configuration:
2 | # https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/configuration-options-for-dependency-updates
3 |
4 | version: 2
5 | updates:
6 | # Maintain dependencies for Gradle dependencies
7 | - package-ecosystem: "gradle"
8 | directory: "/"
9 | target-branch: "next"
10 | schedule:
11 | interval: "daily"
12 | # Maintain dependencies for GitHub Actions
13 | - package-ecosystem: "github-actions"
14 | directory: "/"
15 | target-branch: "next"
16 | schedule:
17 | interval: "daily"
18 |
--------------------------------------------------------------------------------
/.github/workflows/build-frontend.yml:
--------------------------------------------------------------------------------
1 | name: Frontend CI
2 |
3 | on: [ push ]
4 |
5 | permissions:
6 | contents: write
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 | defaults:
12 | run:
13 | working-directory: ./choc-ui
14 |
15 | steps:
16 | - name: Checkout
17 | uses: actions/checkout@v3
18 |
19 | - name: Install Node.js
20 | uses: actions/setup-node@v3
21 | with:
22 | node-version: 18
23 |
24 | - uses: pnpm/action-setup@v2
25 | name: Install pnpm
26 | with:
27 | version: 8
28 | run_install: false
29 |
30 | - name: Get pnpm store directory
31 | shell: bash
32 | run: |
33 | echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
34 |
35 | - uses: actions/cache@v3
36 | name: Setup pnpm cache
37 | with:
38 | path: ${{ env.STORE_PATH }}
39 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
40 | restore-keys: |
41 | ${{ runner.os }}-pnpm-store-
42 |
43 | - name: Install dependencies
44 | run: pnpm install --no-frozen-lockfile
45 |
46 | - name: Build my App
47 | run: npm run build
48 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: [ push ]
4 |
5 | jobs:
6 | build:
7 | strategy:
8 | matrix:
9 | os: [ macos-latest, ubuntu-latest, windows-latest ]
10 | runs-on: ${{ matrix.os }}
11 |
12 | steps:
13 | - uses: actions/checkout@v3
14 | with:
15 | fetch-depth: 10
16 | - uses: actions/setup-java@v3
17 | with:
18 | distribution: 'zulu'
19 | java-version: '17'
20 |
21 | - name: Setup Gradle
22 | uses: gradle/gradle-build-action@v2.8.0
23 | with:
24 | arguments: build
25 |
26 | - name: Execute Gradle build
27 | run: ./gradlew build
28 |
29 | - name: Execute Gradle Coverage
30 | run: ./gradlew check
31 |
32 | - name: Execute Gradle Coverage
33 | if: runner.os == 'macOS'
34 | run: bash <(curl -s https://codecov.io/bash)
35 |
--------------------------------------------------------------------------------
/.github/workflows/release.yaml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 |
8 | jobs:
9 | publish:
10 | runs-on: ubuntu-latest
11 | strategy:
12 | matrix:
13 | assets:
14 | - server/build/libs/server-*.jar
15 | - llm-modules/prompt-script/build/libs/prompt-script-*-all.jar
16 |
17 | permissions:
18 | contents: write
19 | packages: write
20 | steps:
21 | - uses: actions/checkout@v3
22 | - uses: actions/setup-java@v3
23 | with:
24 | distribution: 'zulu'
25 | java-version: '17'
26 | cache: 'gradle'
27 |
28 | - name: Setup Gradle
29 | run: ./gradlew build --no-daemon -x test
30 |
31 | - name: Upload assets to release
32 | uses: svenstaro/upload-release-action@v2
33 | with:
34 | repo_token: ${{ secrets.GITHUB_TOKEN }}
35 | file: ${{ matrix.assets }}
36 | tag: ${{ github.ref }}
37 | overwrite: true
38 | file_glob: true
39 |
40 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | .gradle
3 | build/
4 | !gradle/wrapper/gradle-wrapper.jar
5 | !**/src/main/**/build/
6 | !**/src/test/**/build/
7 |
8 | ### STS ###
9 | .apt_generated
10 | .classpath
11 | .factorypath
12 | .project
13 | .settings
14 | .springBeans
15 | .sts4-cache
16 | bin/
17 | !**/src/main/**/bin/
18 | !**/src/test/**/bin/
19 |
20 | ### IntelliJ IDEA ###
21 | .idea
22 | *.iws
23 | *.iml
24 | *.ipr
25 | out/
26 | !**/src/main/**/out/
27 | !**/src/test/**/out/
28 |
29 | ### NetBeans ###
30 | /nbproject/private/
31 | /nbbuild/
32 | /dist/
33 | /nbdist/
34 | /.nb-gradle/
35 |
36 | ### VS Code ###
37 | .vscode/
38 | .env
39 | server/src/main/resources/application-dev.yml
40 | server/src/main/resources/frontend/components/mui-components.json
41 | devops-genius.yml
42 | connection.yml
43 |
--------------------------------------------------------------------------------
/CNAME:
--------------------------------------------------------------------------------
1 | framework.unitmesh.cc
2 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM gradle:jdk11 as build
2 | WORKDIR /app
3 | COPY . .
4 | RUN rm -rf choc-ui
5 | RUN ./gradlew build -x test --no-daemon
6 |
7 | FROM openjdk:11-jdk
8 | WORKDIR /app
9 | COPY --from=build /app/server/build/libs/server-*.jar app.jar
10 | RUN ls -la
11 | ENV OPENAI_HOST "https://api.openai.com/"
12 | ENV OPENAI_API_KEY ""
13 | CMD ["java", "-jar", "app.jar"]
14 | EXPOSE 18080
--------------------------------------------------------------------------------
/_fixtures/testing/.gitignore:
--------------------------------------------------------------------------------
1 | venv
--------------------------------------------------------------------------------
/_fixtures/testing/requirements.txt:
--------------------------------------------------------------------------------
1 | sentence-transformers
--------------------------------------------------------------------------------
/_fixtures/testing/st.py:
--------------------------------------------------------------------------------
1 | from sentence_transformers import SentenceTransformer
2 |
3 | # Download model
4 | model = SentenceTransformer('paraphrase-MiniLM-L6-v2')
5 |
6 | # The sentences we'd like to encode
7 | sentences = ['Python is an interpreted high-level general-purpose programming language.',
8 | 'Python is dynamically-typed and garbage-collected.',
9 | 'The quick brown fox jumps over the lazy dog.']
10 |
11 | # Get embeddings of sentences
12 | embeddings = model.encode(sentences)
13 |
14 | # Print the embeddings
15 | for sentence, embedding in zip(sentences, embeddings):
16 | print("Sentence:", sentence)
17 | print("Embedding:", embedding.__len__())
18 | print("")
19 |
--------------------------------------------------------------------------------
/choc-ui/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain
2 | # consistent coding styles between different editors and IDEs.
3 |
4 | root = true
5 |
6 | [*]
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 | indent_style = space
12 | indent_size = 2
13 |
14 | [*.md]
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/choc-ui/.env.example:
--------------------------------------------------------------------------------
1 | # You must first activate a Billing Account here: https://platform.openai.com/account/billing/overview
2 | # Then get your OpenAI API Key here: https://platform.openai.com/account/api-keys
3 | # OPENAI_API_KEY=XXXXXXXX
4 |
5 | # Set the following only when deployed. In this example, we can reuse the same OAuth app, but if you are storing users, we recommend using a different OAuth app for development/production so that you don't mix your test and production user base.
6 | # AUTH_REDIRECT_PROXY_URL=https://YOURAPP.vercel.app/api/auth
7 |
8 | # Instructions to create kv database here: https://vercel.com/docs/storage/vercel-kv/quickstart and
9 | #KV_URL=XXXXXXXX
10 | #KV_REST_API_URL=XXXXXXXX
11 | #KV_REST_API_TOKEN=XXXXXXXX
12 | #KV_REST_API_READ_ONLY_TOKEN=XXXXXXXX
13 | #NEXT_PUBLIC_API_SERVER_URL=http://localhost:18080
14 |
15 |
--------------------------------------------------------------------------------
/choc-ui/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/eslintrc",
3 | "root": true,
4 | "extends": [
5 | "next/core-web-vitals",
6 | "prettier",
7 | "plugin:tailwindcss/recommended"
8 | ],
9 | "plugins": ["tailwindcss"],
10 | "rules": {
11 | "tailwindcss/no-custom-classname": "off"
12 | },
13 | "settings": {
14 | "tailwindcss": {
15 | "callees": ["cn", "cva"],
16 | "config": "tailwind.config.js"
17 | }
18 | },
19 | "overrides": [
20 | {
21 | "files": ["*.ts", "*.tsx"],
22 | "parser": "@typescript-eslint/parser"
23 | }
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/choc-ui/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 | .pnp
6 | .pnp.js
7 |
8 | # testing
9 | coverage
10 |
11 | # next.js
12 | .next/
13 | out/
14 | build
15 |
16 | # misc
17 | .DS_Store
18 | *.pem
19 |
20 | # debug
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 | .pnpm-debug.log*
25 |
26 | # local env files
27 | .env.local
28 | .env.development.local
29 | .env.test.local
30 | .env.production.local
31 |
32 | # turbo
33 | .turbo
34 |
35 | .contentlayer
36 | .env
37 | .vercel
38 | .vscode
39 | .swc
40 |
--------------------------------------------------------------------------------
/choc-ui/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2023 Vercel, Inc.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
--------------------------------------------------------------------------------
/choc-ui/app/editor/page.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import LiveEditor from "@/components/editor/live-editor";
4 | import {cn} from "@/lib/utils";
5 |
6 | export default function IndexPage() {
7 | return
8 |
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/choc-ui/app/page.tsx:
--------------------------------------------------------------------------------
1 | import { nanoid } from '@/lib/utils'
2 | import { Chat } from '@/components/chat'
3 |
4 | // export const runtime = 'edge'
5 |
6 | export default function IndexPage() {
7 | const id = nanoid()
8 |
9 | return
10 | }
11 |
--------------------------------------------------------------------------------
/choc-ui/assets/fonts/Inter-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unit-mesh/choco-builder/fdd4d700f9dc04d0bdef3bbc41b8955804cad135/choc-ui/assets/fonts/Inter-Bold.woff
--------------------------------------------------------------------------------
/choc-ui/assets/fonts/Inter-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unit-mesh/choco-builder/fdd4d700f9dc04d0bdef3bbc41b8955804cad135/choc-ui/assets/fonts/Inter-Regular.woff
--------------------------------------------------------------------------------
/choc-ui/components/button-scroll-to-bottom.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import * as React from 'react'
4 |
5 | import { cn } from '@/lib/utils'
6 | import { useAtBottom } from '@/lib/hooks/use-at-bottom'
7 | import { Button, type ButtonProps } from '@/components/ui/button'
8 | import { IconArrowDown } from '@/components/ui/icons'
9 |
10 | export function ButtonScrollToBottom({ className, ...props }: ButtonProps) {
11 | const isAtBottom = useAtBottom()
12 |
13 | return (
14 |
33 | )
34 | }
35 |
--------------------------------------------------------------------------------
/choc-ui/components/chat-list.tsx:
--------------------------------------------------------------------------------
1 | import { type Message } from 'ai'
2 |
3 | import { Separator } from '@/components/ui/separator'
4 | import { ChatMessage } from '@/components/chat-message'
5 |
6 | export interface ChatList {
7 | messages: Message[]
8 | }
9 |
10 | export function ChatList({ messages }: ChatList) {
11 | if (!messages.length) {
12 | return null
13 | }
14 |
15 | return (
16 |
17 | {messages.map((message, index) => (
18 |
19 |
20 | {index < messages.length - 1 && (
21 |
22 | )}
23 |
24 | ))}
25 |
26 | )
27 | }
28 |
--------------------------------------------------------------------------------
/choc-ui/components/chat-message-actions.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { type Message } from 'ai'
4 |
5 | import { Button } from '@/components/ui/button'
6 | import { IconCheck, IconCopy } from '@/components/ui/icons'
7 | import { useCopyToClipboard } from '@/lib/hooks/use-copy-to-clipboard'
8 | import { cn } from '@/lib/utils'
9 |
10 | interface ChatMessageActionsProps extends React.ComponentProps<'div'> {
11 | message: Message
12 | }
13 |
14 | export function ChatMessageActions({
15 | message,
16 | className,
17 | ...props
18 | }: ChatMessageActionsProps) {
19 | const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 })
20 |
21 | const onCopy = () => {
22 | if (isCopied) return
23 | copyToClipboard(message.content)
24 | }
25 |
26 | return (
27 |
34 |
38 |
39 | )
40 | }
41 |
--------------------------------------------------------------------------------
/choc-ui/components/chat-scroll-anchor.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import * as React from 'react'
4 | import { useInView } from 'react-intersection-observer'
5 |
6 | import { useAtBottom } from '@/lib/hooks/use-at-bottom'
7 |
8 | interface ChatScrollAnchorProps {
9 | trackVisibility?: boolean
10 | }
11 |
12 | export function ChatScrollAnchor({ trackVisibility }: ChatScrollAnchorProps) {
13 | const isAtBottom = useAtBottom()
14 | const { ref, entry, inView } = useInView({
15 | trackVisibility,
16 | delay: 100,
17 | rootMargin: '0px 0px -150px 0px'
18 | })
19 |
20 | React.useEffect(() => {
21 | if (isAtBottom && trackVisibility && !inView) {
22 | entry?.target.scrollIntoView({
23 | block: 'start'
24 | })
25 | }
26 | }, [inView, entry, isAtBottom, trackVisibility])
27 |
28 | return
29 | }
30 |
--------------------------------------------------------------------------------
/choc-ui/components/dsl/design-block.tsx:
--------------------------------------------------------------------------------
1 | import { DesignDslRender } from '@/components/dsl/design-dsl-render'
2 | import { useEffect, useState } from 'react'
3 | import {CodeBlock} from "@/components/ui/codeblock";
4 |
5 | interface DslOutput {
6 | name: string
7 | description: string
8 | output: any
9 | dsl: any
10 | }
11 |
12 | export function DesignBlock({ value }: { value: string }) {
13 | const [dsl, setDsl] = useState(null)
14 |
15 | useEffect(() => {
16 | fetch(`/api/dsl/Design`, {
17 | method: 'POST',
18 | headers: {
19 | 'Content-Type': 'application/json;charset=UTF-8'
20 | },
21 | body: JSON.stringify({ dsl: value })
22 | })
23 | .then(res => res.json())
24 | .then((data: DslOutput) => {
25 | setDsl(data.output)
26 | })
27 | }, [])
28 |
29 | if (!dsl) {
30 | return
31 | }
32 |
33 | if (dsl.layouts.length == 0) {
34 | return
35 | }
36 |
37 | return
38 | }
39 |
--------------------------------------------------------------------------------
/choc-ui/components/editor/styles.css:
--------------------------------------------------------------------------------
1 | /* Basic editor styles */
2 | .tiptap > * + * {
3 | margin-top: 0.75em;
4 | }
5 | .tiptap ul, .tiptap ol {
6 | padding: 0 1rem;
7 | }
8 | .tiptap h1, .tiptap h2, .tiptap h3, .tiptap h4, .tiptap h5, .tiptap h6 {
9 | line-height: 1.1;
10 | }
11 | .tiptap code {
12 | background-color: rgba(97, 97, 97, 0.1);
13 | color: #616161;
14 | }
15 | .tiptap pre {
16 | background: #0d0d0d;
17 | color: #fff;
18 | font-family: 'JetBrainsMono', monospace;
19 | padding: 0.75rem 1rem;
20 | border-radius: 0.5rem;
21 | }
22 | .tiptap pre code {
23 | color: inherit;
24 | padding: 0;
25 | background: none;
26 | font-size: 0.8rem;
27 | }
28 | .tiptap img {
29 | max-width: 100%;
30 | height: auto;
31 | }
32 | .tiptap blockquote {
33 | padding-left: 1rem;
34 | border-left: 2px solid rgba(13, 13, 13, 0.1);
35 | }
36 | .tiptap hr {
37 | border: none;
38 | border-top: 2px solid rgba(13, 13, 13, 0.1);
39 | margin: 2rem 0;
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/choc-ui/components/external-link.tsx:
--------------------------------------------------------------------------------
1 | export function ExternalLink({
2 | href,
3 | children
4 | }: {
5 | href: string
6 | children: React.ReactNode
7 | }) {
8 | return (
9 |
14 | {children}
15 |
27 |
28 | )
29 | }
30 |
--------------------------------------------------------------------------------
/choc-ui/components/footer.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | import { cn } from '@/lib/utils'
4 | import { ExternalLink } from '@/components/external-link'
5 | import {Span} from "next/dist/server/lib/trace/tracer";
6 |
7 | export function FooterText({ className, ...props }: React.ComponentProps<'p'>) {
8 | return (
9 |
16 | Open source LLM helper factor built with{' '}
17 |
18 | ChocoBuilder
19 |
20 | .
21 |
22 | )
23 | }
24 |
--------------------------------------------------------------------------------
/choc-ui/components/header.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import Link from 'next/link'
3 |
4 | import { cn } from '@/lib/utils'
5 | import { buttonVariants } from '@/components/ui/button'
6 | import { IconGitHub } from '@/components/ui/icons'
7 |
8 | export async function Header() {
9 | return (
10 |
28 | )
29 | }
30 |
--------------------------------------------------------------------------------
/choc-ui/components/interpreter/message.ts:
--------------------------------------------------------------------------------
1 | export type InterpreterMessage = {
2 | id: number
3 | resultValue: string
4 | displayValue: string
5 | className: string
6 | msgType: MsgType
7 | content: MessageContent
8 | }
9 |
10 | export type MsgType = 'none' | 'error' | 'html' | 'running'
11 |
12 | export type MessageContent = {
13 | type: string
14 | // when type is "cc.unitmesh.code.messaging.HtmlContent"
15 | html?: string
16 | }
17 |
--------------------------------------------------------------------------------
/choc-ui/components/markdown.tsx:
--------------------------------------------------------------------------------
1 | import { FC, memo } from 'react'
2 | import ReactMarkdown, { Options } from 'react-markdown'
3 |
4 | export const MemoizedReactMarkdown: FC = memo(
5 | ReactMarkdown,
6 | (prevProps, nextProps) =>
7 | prevProps.children === nextProps.children &&
8 | prevProps.className === nextProps.className
9 | )
10 |
--------------------------------------------------------------------------------
/choc-ui/components/providers.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import * as React from 'react'
4 | import { ThemeProvider as NextThemesProvider } from 'next-themes'
5 | import { ThemeProviderProps } from 'next-themes/dist/types'
6 |
7 | import { TooltipProvider } from '@/components/ui/tooltip'
8 |
9 | export function Providers({ children, ...props }: ThemeProviderProps) {
10 | return (
11 |
12 | {children}
13 |
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/choc-ui/components/sidebar-footer.tsx:
--------------------------------------------------------------------------------
1 | import { cn } from '@/lib/utils'
2 |
3 | export function SidebarFooter({
4 | children,
5 | className,
6 | ...props
7 | }: React.ComponentProps<'div'>) {
8 | return (
9 |
13 | {children}
14 |
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/choc-ui/components/sidebar.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import * as React from 'react'
4 |
5 | import { Button } from '@/components/ui/button'
6 | import {
7 | Sheet,
8 | SheetContent,
9 | SheetHeader,
10 | SheetTitle,
11 | SheetTrigger
12 | } from '@/components/ui/sheet'
13 | import { IconSidebar } from '@/components/ui/icons'
14 |
15 | export interface SidebarProps {
16 | children?: React.ReactNode
17 | }
18 |
19 | export function Sidebar({ children }: SidebarProps) {
20 | return (
21 |
22 |
23 |
27 |
28 |
29 |
30 | Chat History
31 |
32 | {children}
33 |
34 |
35 | )
36 | }
37 |
--------------------------------------------------------------------------------
/choc-ui/components/tailwind-indicator.tsx:
--------------------------------------------------------------------------------
1 | export function TailwindIndicator() {
2 | if (process.env.NODE_ENV === 'production') return null
3 |
4 | return (
5 |
6 |
xs
7 |
sm
8 |
md
9 |
lg
10 |
xl
11 |
2xl
12 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/choc-ui/components/theme-toggle.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import * as React from 'react'
4 | import { useTheme } from 'next-themes'
5 |
6 | import { Button } from '@/components/ui/button'
7 | import { IconMoon, IconSun } from '@/components/ui/icons'
8 |
9 | export function ThemeToggle() {
10 | const { setTheme, theme } = useTheme()
11 | const [_, startTransition] = React.useTransition()
12 |
13 | return (
14 |
30 | )
31 | }
32 |
--------------------------------------------------------------------------------
/choc-ui/components/toaster.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | export { Toaster } from 'react-hot-toast'
4 |
--------------------------------------------------------------------------------
/choc-ui/components/ui/badge.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import { cva, type VariantProps } from 'class-variance-authority'
3 |
4 | import { cn } from '@/lib/utils'
5 |
6 | const badgeVariants = cva(
7 | 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
8 | {
9 | variants: {
10 | variant: {
11 | default:
12 | 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
13 | secondary:
14 | 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
15 | destructive:
16 | 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
17 | outline: 'text-foreground'
18 | }
19 | },
20 | defaultVariants: {
21 | variant: 'default'
22 | }
23 | }
24 | )
25 |
26 | export interface BadgeProps
27 | extends React.HTMLAttributes,
28 | VariantProps {}
29 |
30 | function Badge({ className, variant, ...props }: BadgeProps) {
31 | return (
32 |
33 | )
34 | }
35 |
36 | export { Badge, badgeVariants }
37 |
--------------------------------------------------------------------------------
/choc-ui/components/ui/input.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | import { cn } from '@/lib/utils'
4 |
5 | export interface InputProps
6 | extends React.InputHTMLAttributes {}
7 |
8 | const Input = React.forwardRef(
9 | ({ className, type, ...props }, ref) => {
10 | return (
11 |
20 | )
21 | }
22 | )
23 | Input.displayName = 'Input'
24 |
25 | export { Input }
26 |
--------------------------------------------------------------------------------
/choc-ui/components/ui/label.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as LabelPrimitive from "@radix-ui/react-label"
5 | import { cva, type VariantProps } from "class-variance-authority"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const labelVariants = cva(
10 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
11 | )
12 |
13 | const Label = React.forwardRef<
14 | React.ElementRef,
15 | React.ComponentPropsWithoutRef &
16 | VariantProps
17 | >(({ className, ...props }, ref) => (
18 |
23 | ))
24 | Label.displayName = LabelPrimitive.Root.displayName
25 |
26 | export { Label }
27 |
--------------------------------------------------------------------------------
/choc-ui/components/ui/separator.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import * as React from 'react'
4 | import * as SeparatorPrimitive from '@radix-ui/react-separator'
5 |
6 | import { cn } from '@/lib/utils'
7 |
8 | const Separator = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(
12 | (
13 | { className, orientation = 'horizontal', decorative = true, ...props },
14 | ref
15 | ) => (
16 |
27 | )
28 | )
29 | Separator.displayName = SeparatorPrimitive.Root.displayName
30 |
31 | export { Separator }
32 |
--------------------------------------------------------------------------------
/choc-ui/components/ui/textarea.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | import { cn } from '@/lib/utils'
4 |
5 | export interface TextareaProps
6 | extends React.TextareaHTMLAttributes {}
7 |
8 | const Textarea = React.forwardRef(
9 | ({ className, ...props }, ref) => {
10 | return (
11 |
19 | )
20 | }
21 | )
22 | Textarea.displayName = 'Textarea'
23 |
24 | export { Textarea }
25 |
--------------------------------------------------------------------------------
/choc-ui/components/ui/tooltip.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import * as React from 'react'
4 | import * as TooltipPrimitive from '@radix-ui/react-tooltip'
5 |
6 | import { cn } from '@/lib/utils'
7 |
8 | const TooltipProvider = TooltipPrimitive.Provider
9 |
10 | const Tooltip = TooltipPrimitive.Root
11 |
12 | const TooltipTrigger = TooltipPrimitive.Trigger
13 |
14 | const TooltipContent = React.forwardRef<
15 | React.ElementRef,
16 | React.ComponentPropsWithoutRef
17 | >(({ className, sideOffset = 4, ...props }, ref) => (
18 |
27 | ))
28 | TooltipContent.displayName = TooltipPrimitive.Content.displayName
29 |
30 | export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
31 |
--------------------------------------------------------------------------------
/choc-ui/components/workflow/prompt-example.ts:
--------------------------------------------------------------------------------
1 | export interface PromptExample {
2 | question: string
3 | answer: string
4 | }
5 |
6 | export class QAExample implements PromptExample {
7 | question: string
8 | answer: string
9 |
10 | constructor(question: string, answer: string) {
11 | this.question = question
12 | this.answer = answer
13 | }
14 | }
15 |
16 | export class QAUpdateExample implements PromptExample {
17 | question: string
18 | answer: string
19 | nextAction: string
20 | finalOutput: string
21 |
22 | constructor(
23 | question: string,
24 | answer: string,
25 | nextAction: string = '',
26 | finalOutput: string = ''
27 | ) {
28 | this.question = question
29 | this.answer = answer
30 | this.nextAction = nextAction
31 | this.finalOutput = finalOutput
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/choc-ui/components/workflow/stage.ts:
--------------------------------------------------------------------------------
1 | export enum Stage {
2 | // 问题归类
3 | Classify = 'Classify',
4 | // 问题澄清
5 | Clarify = 'Clarify',
6 | // 问题分析
7 | Analyze = 'Analyze',
8 | // 解决方案设计
9 | Design = 'Design',
10 | // 解决方案实现
11 | Execute = 'Execute',
12 | Custom = 'Custom'
13 | }
14 |
--------------------------------------------------------------------------------
/choc-ui/components/workflow/workflow-dto.ts:
--------------------------------------------------------------------------------
1 | import { Message } from 'ai'
2 | import { Stage } from '@/components/workflow/stage'
3 |
4 | export type MessageResponse = {
5 | id: string
6 | result?: WorkflowResult
7 | created: number
8 | isFlowable: boolean
9 | messages: Message[]
10 | }
11 |
12 | export type WorkflowResult = {
13 | currentStage: Stage
14 | nextStage: Stage
15 | responseMsg: string
16 | resultType: string
17 | result: string
18 | }
19 |
--------------------------------------------------------------------------------
/choc-ui/docs/test-case-1.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## 编写
4 |
5 | 完整场景:
6 |
7 | ```markdown
8 | 使用响应式布局,编写一个聊天页面
9 | ```
10 |
11 | 不完整场景:
12 |
13 | ```markdown
14 | 编写一个聊天页,布局方式:响应式,其中左边是一个聊天列表页,中间是聊天区(使用卡片),聊天区的下方是输入区。
15 | ```
16 |
17 | ### Step 3
18 |
--------------------------------------------------------------------------------
/choc-ui/jest.config.js:
--------------------------------------------------------------------------------
1 | const nextJest = require('next/jest')
2 |
3 | const createJestConfig = nextJest({
4 | // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
5 | dir: './',
6 | })
7 |
8 | // Add any custom config to be passed to Jest
9 | const customJestConfig = {
10 | setupFilesAfterEnv: ['/jest.setup.js'],
11 | testEnvironment: 'jest-environment-jsdom',
12 | }
13 |
14 | // createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
15 | module.exports = createJestConfig(customJestConfig)
16 |
--------------------------------------------------------------------------------
/choc-ui/jest.setup.js:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom'
2 |
--------------------------------------------------------------------------------
/choc-ui/lib/fonts.ts:
--------------------------------------------------------------------------------
1 | import { JetBrains_Mono as FontMono, Inter as FontSans } from 'next/font/google'
2 |
3 | export const fontSans = FontSans({
4 | subsets: ['latin'],
5 | variable: '--font-sans'
6 | })
7 |
8 | export const fontMono = FontMono({
9 | subsets: ['latin'],
10 | variable: '--font-mono'
11 | })
12 |
--------------------------------------------------------------------------------
/choc-ui/lib/hooks/use-at-bottom.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | export function useAtBottom(offset = 0) {
4 | const [isAtBottom, setIsAtBottom] = React.useState(false)
5 |
6 | React.useEffect(() => {
7 | const handleScroll = () => {
8 | setIsAtBottom(
9 | window.innerHeight + window.scrollY >=
10 | document.body.offsetHeight - offset
11 | )
12 | }
13 |
14 | window.addEventListener('scroll', handleScroll, { passive: true })
15 | handleScroll()
16 |
17 | return () => {
18 | window.removeEventListener('scroll', handleScroll)
19 | }
20 | }, [offset])
21 |
22 | return isAtBottom
23 | }
24 |
--------------------------------------------------------------------------------
/choc-ui/lib/hooks/use-copy-to-clipboard.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import * as React from 'react'
4 |
5 | export interface useCopyToClipboardProps {
6 | timeout?: number
7 | }
8 |
9 | export function useCopyToClipboard({
10 | timeout = 2000
11 | }: useCopyToClipboardProps) {
12 | const [isCopied, setIsCopied] = React.useState(false)
13 |
14 | const copyToClipboard = (value: string) => {
15 | if (typeof window === 'undefined' || !navigator.clipboard?.writeText) {
16 | return
17 | }
18 |
19 | if (!value) {
20 | return
21 | }
22 |
23 | navigator.clipboard.writeText(value).then(() => {
24 | setIsCopied(true)
25 |
26 | setTimeout(() => {
27 | setIsCopied(false)
28 | }, timeout)
29 | })
30 | }
31 |
32 | return { isCopied, copyToClipboard }
33 | }
34 |
--------------------------------------------------------------------------------
/choc-ui/lib/hooks/use-enter-submit.tsx:
--------------------------------------------------------------------------------
1 | import { useRef, type RefObject } from 'react'
2 |
3 | export function useEnterSubmit(): {
4 | formRef: RefObject
5 | onKeyDown: (event: React.KeyboardEvent) => void
6 | } {
7 | const formRef = useRef(null)
8 |
9 | const handleKeyDown = (
10 | event: React.KeyboardEvent
11 | ): void => {
12 | if (
13 | event.key === 'Enter' &&
14 | !event.shiftKey &&
15 | !event.nativeEvent.isComposing
16 | ) {
17 | formRef.current?.requestSubmit()
18 | event.preventDefault()
19 | }
20 | }
21 |
22 | return { formRef, onKeyDown: handleKeyDown }
23 | }
24 |
--------------------------------------------------------------------------------
/choc-ui/lib/hooks/use-local-storage.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react'
2 |
3 | export const useLocalStorage = (
4 | key: string,
5 | initialValue: T
6 | ): [T, (value: T) => void] => {
7 | const [storedValue, setStoredValue] = useState(initialValue)
8 |
9 | useEffect(() => {
10 | // Retrieve from localStorage
11 | const item = window.localStorage.getItem(key)
12 | if (item) {
13 | setStoredValue(JSON.parse(item))
14 | }
15 | }, [key])
16 |
17 | const setValue = (value: T) => {
18 | // Save state
19 | setStoredValue(value)
20 | // Save to localStorage
21 | window.localStorage.setItem(key, JSON.stringify(value))
22 | }
23 | return [storedValue, setValue]
24 | }
25 |
--------------------------------------------------------------------------------
/choc-ui/lib/types.ts:
--------------------------------------------------------------------------------
1 | import { type Message } from 'ai'
2 |
3 | export interface Chat extends Record {
4 | id: string
5 | title: string
6 | createdAt: Date
7 | userId: string
8 | path: string
9 | messages: Message[]
10 | sharePath?: string
11 | }
12 |
13 | export type ServerActionResult = Promise<
14 | | Result
15 | | {
16 | error: string
17 | }
18 | >
19 |
--------------------------------------------------------------------------------
/choc-ui/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { clsx, type ClassValue } from 'clsx'
2 | import { customAlphabet } from 'nanoid'
3 | import { twMerge } from 'tailwind-merge'
4 |
5 | export function cn(...inputs: ClassValue[]) {
6 | return twMerge(clsx(inputs))
7 | }
8 |
9 | export const nanoid = customAlphabet(
10 | '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
11 | 7
12 | ) // 7-character random string
13 |
14 | export async function fetcher(
15 | input: RequestInfo,
16 | init?: RequestInit
17 | ): Promise {
18 | const res = await fetch(input, init)
19 |
20 | if (!res.ok) {
21 | const json = await res.json()
22 | if (json.error) {
23 | const error = new Error(json.error) as Error & {
24 | status: number
25 | }
26 | error.status = res.status
27 | throw error
28 | } else {
29 | throw new Error('An unexpected error occurred')
30 | }
31 | }
32 |
33 | return res.json()
34 | }
35 |
36 | export function formatDate(input: string | number | Date): string {
37 | const date = new Date(input)
38 | return date.toLocaleDateString('en-US', {
39 | month: 'long',
40 | day: 'numeric',
41 | year: 'numeric'
42 | })
43 | }
44 |
--------------------------------------------------------------------------------
/choc-ui/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/choc-ui/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | module.exports = {
3 | output: "standalone",
4 | reactStrictMode: true,
5 | experimental: {
6 | // serverActions: true,
7 | proxyTimeout: 120_000,
8 | },
9 | async rewrites() {
10 | return [
11 | {
12 | source: '/api/:path*',
13 | destination: 'http://localhost:18080/api/:path*'
14 | }
15 | ]
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/choc-ui/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/choc-ui/prettier.config.cjs:
--------------------------------------------------------------------------------
1 | /** @type {import('prettier').Config} */
2 | module.exports = {
3 | endOfLine: 'lf',
4 | semi: false,
5 | useTabs: false,
6 | singleQuote: true,
7 | arrowParens: 'avoid',
8 | tabWidth: 2,
9 | trailingComma: 'none',
10 | importOrder: [
11 | '^(react/(.*)$)|^(react$)',
12 | '^(next/(.*)$)|^(next$)',
13 | '',
14 | '',
15 | '^types$',
16 | '^@/types/(.*)$',
17 | '^@/config/(.*)$',
18 | '^@/lib/(.*)$',
19 | '^@/hooks/(.*)$',
20 | '^@/components/ui/(.*)$',
21 | '^@/components/(.*)$',
22 | '^@/registry/(.*)$',
23 | '^@/styles/(.*)$',
24 | '^@/app/(.*)$',
25 | '',
26 | '^[./]'
27 | ],
28 | importOrderSeparation: false,
29 | importOrderSortSpecifiers: true,
30 | importOrderBuiltinModulesToTop: true,
31 | importOrderParserPlugins: ['typescript', 'jsx', 'decorators-legacy'],
32 | importOrderMergeDuplicateImports: true,
33 | importOrderCombineTypeAndValueImports: true
34 | }
35 |
--------------------------------------------------------------------------------
/choc-ui/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unit-mesh/choco-builder/fdd4d700f9dc04d0bdef3bbc41b8955804cad135/choc-ui/public/favicon-16x16.png
--------------------------------------------------------------------------------
/choc-ui/public/thirteen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/choc-ui/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/choc-ui/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["dom", "dom.iterable", "esnext"],
4 | "allowJs": true,
5 | "skipLibCheck": true,
6 | "strict": true,
7 | "forceConsistentCasingInFileNames": true,
8 | "noEmit": true,
9 | "incremental": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "baseUrl": ".",
17 | "paths": {
18 | "@/*": ["./*"]
19 | },
20 | "plugins": [
21 | {
22 | "name": "next"
23 | }
24 | ],
25 | "strictNullChecks": true
26 | },
27 | "include": [
28 | "next-env.d.ts",
29 | "next-auth.d.ts",
30 | "**/*.ts",
31 | "**/*.tsx",
32 | ".next/types/**/*.ts"
33 | ],
34 | "exclude": ["node_modules"]
35 | }
36 |
--------------------------------------------------------------------------------
/cocoa-core/README.md:
--------------------------------------------------------------------------------
1 | # Cocoa Core
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/cocoa-core/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(libs.plugins.jvm)
3 | alias(libs.plugins.serialization)
4 | }
5 |
6 | dependencies {
7 | implementation(libs.kotlin.stdlib)
8 | implementation(libs.coroutines.core)
9 | implementation(libs.serialization.json)
10 | implementation(libs.jtokkit)
11 |
12 | implementation(libs.gson)
13 | implementation(libs.rxjava3)
14 |
15 | implementation(kotlin("reflect"))
16 | implementation(libs.reflections)
17 |
18 | implementation(libs.velocity.engine)
19 | implementation(libs.jackson.module.kotlin)
20 |
21 | testImplementation(libs.bundles.test)
22 | testRuntimeOnly(libs.test.junit.engine)
23 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/agent/Tool.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.agent
2 |
3 |
4 | @Retention(AnnotationRetention.RUNTIME)
5 | @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER,
6 | AnnotationTarget.CLASS
7 | )
8 | annotation class Tool(
9 | val name: String = "",
10 | vararg val value: String = [""],
11 | )
12 |
13 |
14 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/Domain.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core
2 |
3 | @Target(AnnotationTarget.CLASS)
4 | @Retention(AnnotationRetention.SOURCE)
5 | @MustBeDocumented
6 | annotation class Domain(
7 | val name: String,
8 | val description: String,
9 | )
10 |
11 | @Target(AnnotationTarget.CLASS)
12 | @Retention(AnnotationRetention.SOURCE)
13 | @MustBeDocumented
14 | annotation class SubDomain(
15 | val name: String,
16 | val description: String,
17 | )
18 |
19 | annotation class ToolSchema(
20 | val name: String,
21 | val args: Array,
22 | )
23 |
24 |
25 | @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
26 | @Retention(AnnotationRetention.SOURCE)
27 | @MustBeDocumented
28 | annotation class Tool(
29 | val name: String,
30 | val description: String,
31 | val schemas: Array = [],
32 | val examples: Array = [],
33 | )
34 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/cache/CachableEmbedding.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.cache
2 |
3 | import cc.unitmesh.nlp.embedding.Embedding
4 |
5 | public interface CachableEmbedding {
6 | fun create(text: String): Embedding
7 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/context/DslContext.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.context
2 |
3 | import cc.unitmesh.cf.core.dsl.InterpreterContext
4 |
5 | abstract class DslContext(
6 | /**
7 | * 最相关的 interpreter
8 | */
9 | val nearestInterpreters: List,
10 | val chatHistories: String,
11 | ) {
12 | /**
13 | * resolve variables in prompts, to make them more human-friendly
14 | * should consider use [cc.unitmesh.cf.core.context.variable.VariableResolver] to resolve variables
15 | */
16 | abstract fun compileVariable(text: String): String
17 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/context/DslContextBuilder.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.context
2 |
3 | import cc.unitmesh.cf.core.cache.CachableEmbedding
4 | import cc.unitmesh.cf.core.dsl.InterpreterContext
5 | import cc.unitmesh.nlp.similarity.Similarity
6 |
7 | abstract class DslContextBuilder(
8 | private val similarity: Similarity,
9 | private val cachedEmbedding: CachableEmbedding
10 | ) {
11 | abstract fun buildFor(domain: InterpreterContext, question: String, chatHistories: String = ""): DslContext
12 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/context/variable/Variable.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.context.variable
2 |
3 | @Target(AnnotationTarget.CLASS)
4 | @Retention(AnnotationRetention.SOURCE)
5 | @MustBeDocumented
6 | annotation class Variable(
7 | // 变量名
8 | val name: String
9 | )
10 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/context/variable/VariableResolver.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.context.variable
2 |
3 | import org.apache.velocity.VelocityContext
4 | import org.apache.velocity.app.Velocity
5 | import java.io.StringWriter
6 |
7 | interface VariableResolver {
8 | var variables: T?
9 |
10 | val velocityContext: VelocityContext
11 |
12 | fun resolve(question: String = "") {}
13 |
14 | fun put(key: String, value: Any) {
15 | velocityContext.put(key, value)
16 | }
17 |
18 | fun get(key: String): Any? {
19 | return velocityContext.get(key)
20 | }
21 |
22 | fun compile(input: String): String {
23 | val sw = StringWriter()
24 | Velocity.evaluate(velocityContext, sw, "#" + this.javaClass.name, input)
25 | return sw.toString()
26 | }
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/dsl/Dsl.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.dsl
2 |
3 | interface Dsl {
4 | var domain: String
5 |
6 | /**
7 | * the Display content for ChatUI
8 | */
9 | val content: String
10 | var interpreters: List
11 | }
12 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/dsl/DslCompiler.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.dsl
2 |
3 | interface DslCompiler {
4 | fun compile(dsl: Dsl): Any
5 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/dsl/DslInterpreter.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.dsl
2 |
3 | import cc.unitmesh.nlp.embedding.EmbeddingElement
4 | import cc.unitmesh.cf.core.utils.IdUtil
5 | import com.fasterxml.jackson.annotation.JsonIgnore
6 | import kotlinx.serialization.Serializable
7 |
8 | @Serializable
9 | class DslInterpreter(
10 | override val id: String = IdUtil.uuid(),
11 | override val name: String,
12 | val description: String,
13 | ): EmbeddingElement {
14 | @JsonIgnore
15 | override lateinit var embedding: List
16 | }
17 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/dsl/IndexElement.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.dsl
2 |
3 | public interface IndexElement {
4 | val id: String
5 | val name: String
6 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/dsl/Interpreter.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.dsl
2 |
3 | interface Interpreter {
4 | fun canInterpret(dsl: Dsl): Boolean
5 |
6 | fun interpret(dsl: Dsl): Any
7 | }
8 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/dsl/InterpreterContext.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.dsl
2 |
3 | import cc.unitmesh.nlp.embedding.EmbeddingElement
4 | import cc.unitmesh.cf.core.utils.IdUtil
5 |
6 | abstract class InterpreterContext(
7 | override val id: String = IdUtil.uuid(),
8 | override val name: String,
9 | val description: String,
10 | ) : EmbeddingElement {
11 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/flow/DomainDeclaration.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.flow
2 |
3 | interface DomainDeclaration {
4 | /**
5 | * A domain name should be unique and lower case, also need to be human readable.
6 | */
7 | val domainName: String
8 | val description: String
9 | fun workflow(question: String): Workflow
10 | }
11 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/flow/ProblemAnalyzer.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.flow
2 |
3 | import cc.unitmesh.cf.core.dsl.Dsl
4 |
5 | typealias AnalyzeResult = Dsl;
6 |
7 | interface ProblemAnalyzer {
8 | fun analyze(domain: String, question: String): Dsl
9 | }
10 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/flow/ProblemClarifier.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.flow
2 |
3 | import cc.unitmesh.cf.core.flow.model.FlowActionFlag
4 |
5 |
6 | typealias ClarifyResult = Pair;
7 |
8 | /**
9 | *
10 | */
11 | interface ProblemClarifier {
12 | fun clarify(domain: String, question: String, histories: List = emptyList()): Pair
13 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/flow/SolutionDesigner.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.flow
2 |
3 | import cc.unitmesh.cf.core.dsl.Dsl
4 |
5 | typealias DesignResult = Dsl;
6 |
7 | interface SolutionDesigner {
8 | fun design(domain: String, question: String, histories: List = emptyList()): Dsl
9 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/flow/SolutionExecutor.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.flow
2 |
3 | import cc.unitmesh.cf.core.dsl.Dsl
4 | import cc.unitmesh.cf.core.dsl.Interpreter
5 | import cc.unitmesh.cf.core.flow.model.Answer
6 | import io.reactivex.rxjava3.core.Flowable
7 |
8 | typealias ExecuteResult = Answer;
9 |
10 | interface SolutionExecutor {
11 | val interpreters: List
12 | fun execute(solution: T): Flowable
13 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/flow/SolutionReviewer.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.flow
2 |
3 | import cc.unitmesh.cf.core.dsl.Dsl
4 |
5 | interface SolutionReviewer {
6 | fun review(question: String, histories: List = emptyList()): Dsl
7 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/flow/model/Answer.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.flow.model
2 |
3 | class Answer(
4 | var executor: String,
5 | var values: Any
6 | ) {
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/flow/model/ChatWebContext.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.flow.model
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | data class ChatWebContext(
6 | var messages: List,
7 | val id: String,
8 | val stage: StageContext.Stage,
9 | ) {
10 | }
11 |
12 | @Serializable
13 | data class Message(val role: String, val content: String)
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/flow/model/WorkflowResult.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.flow.model
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class WorkflowResult(
7 | val currentStage: StageContext.Stage,
8 | val nextStage: StageContext.Stage,
9 | val responseMsg: String,
10 | val resultType: String,
11 | val result: String,
12 | val isFlowable: Boolean = false,
13 | )
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/flow/related/RelatedQueryService.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.flow.related
2 |
3 | /**
4 | * RelatedQueryService is a service that can find related information for a given name.
5 | */
6 | interface RelatedQueryService {
7 | fun findRelated(name: String): Any
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/llms/LlmProvider.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.llms
2 |
3 | import io.reactivex.rxjava3.core.Flowable
4 |
5 | interface LlmProvider {
6 | var temperature: Double
7 |
8 | fun completion(messages: List): String
9 |
10 | fun streamCompletion(messages: List): Flowable
11 |
12 | fun setTemperatureMode(mode: TemperatureMode) {
13 | this.temperature = mode.value
14 | }
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/llms/MockLlmProvider.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.llms
2 |
3 | import io.reactivex.rxjava3.core.Flowable
4 |
5 | class MockLlmProvider(val response: String = "") : LlmProvider {
6 | override var temperature: Double = 0.0
7 |
8 | override fun completion(messages: List): String {
9 | return response
10 | }
11 |
12 | override fun streamCompletion(messages: List): Flowable {
13 | return Flowable.just(response)
14 | }
15 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/llms/TemperatureMode.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.llms
2 |
3 | enum class TemperatureMode(val value: Double) {
4 | Creative(0.7),
5 | Balanced(0.3),
6 | Default(0.0),
7 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/prompt/PromptExample.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.prompt
2 |
3 | interface PromptExample {
4 | val question: String
5 | val answer: String
6 | }
7 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/prompt/QAExample.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.prompt
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | open class QAExample(
7 | override val question: String,
8 | override val answer: String,
9 | ) : PromptExample {
10 |
11 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/prompt/ReActPrompt.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.prompt
2 |
3 | import cc.unitmesh.cf.core.flow.model.FlowActionFlag
4 | import kotlinx.serialization.SerialName
5 | import kotlinx.serialization.Serializable
6 |
7 |
8 | @Serializable
9 | class ReActPrompt(
10 | @SerialName("输入")
11 | override val question: String,
12 | @SerialName("输出")
13 | override val answer: String,
14 | @SerialName("思考")
15 | val thought: String = "",
16 | @SerialName("动作")
17 | val action: FlowActionFlag = FlowActionFlag.CONTINUE,
18 | @SerialName("询问")
19 | val ask: String = "",
20 | @SerialName("最终输出")
21 | val finalOutput: String = "",
22 | ) : PromptExample {
23 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/prompt/StringTemplate.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.prompt
2 |
3 | interface StringTemplate {
4 | fun format(): String
5 | }
6 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/prompt/UpdatableExample.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.prompt
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class UpdatableExample(
7 | override val question: String,
8 | override val answer: String,
9 | val userResponse: String = "",
10 | val finalOutput: String = "",
11 | ) : PromptExample {
12 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/utils/Constants.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.utils
2 |
3 | object Constants {
4 | const val MAX_TOKEN_LENGTH = 10 * 1024 * 1024
5 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/cf/core/utils/IdUtil.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.core.utils
2 |
3 | import java.util.*
4 |
5 | object IdUtil {
6 | fun uuid(): String {
7 | return UUID.randomUUID().toString()
8 | }
9 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/docs/Document.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.docs
2 |
3 | annotation class Document()
4 |
5 | annotation class SampleCode(
6 | val name: String = "",
7 | val content: String = "",
8 | val startBlock: String = "// start-sample",
9 | val endBlock: String = "// end-sample",
10 | )
11 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/embedding/Embedding.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.embedding
2 |
3 | // I don't know why, but sometimes the following import is not added automatically.
4 | typealias Embedding = List
5 |
6 | fun toEmbedding(text: Iterable): Embedding {
7 | return text.map { it.toDouble() }
8 | }
9 |
10 | fun toEmbedding(text: FloatArray): Embedding {
11 | return text.map { it.toDouble() }
12 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/embedding/EmbeddingElement.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.embedding
2 |
3 | import cc.unitmesh.cf.core.dsl.IndexElement
4 |
5 | interface EmbeddingElement: IndexElement {
6 | val embedding: Embedding
7 | }
8 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/embedding/EmbeddingProvider.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.embedding
2 |
3 | import cc.unitmesh.rag.document.Document
4 |
5 | interface EmbeddingProvider {
6 | fun embed(texts: List): List
7 |
8 | fun embed(text: String): Embedding {
9 | val results: List = embed(listOf(text))
10 |
11 | if (results.isNotEmpty()) {
12 | return results[0]
13 | }
14 |
15 | throw CreateEmbeddingFailedException(text)
16 | }
17 |
18 | fun embed(document: Document): Embedding {
19 | return embed(document.text)
20 | }
21 |
22 | class CreateEmbeddingFailedException(val text: String) : RuntimeException("创建嵌入模型失败,原文:$text")
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/embedding/EncodingTokenizer.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.embedding
2 |
3 | interface EncodingTokenizer {
4 | fun encode(text: String): List
5 | fun decode(tokens: List): String
6 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/embedding/OpenAiEncoding.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.embedding
2 |
3 | import com.knuddels.jtokkit.Encodings
4 | import com.knuddels.jtokkit.api.Encoding
5 | import com.knuddels.jtokkit.api.EncodingRegistry
6 | import com.knuddels.jtokkit.api.EncodingType
7 | import com.knuddels.jtokkit.api.IntArrayList
8 |
9 | class OpenAiEncoding : EncodingTokenizer {
10 | private val registry: EncodingRegistry = Encodings.newLazyEncodingRegistry()
11 | private val encoding: Encoding = registry.getEncoding(EncodingType.CL100K_BASE)
12 |
13 | override fun encode(text: String): List {
14 | val encode: IntArrayList = encoding.encode(text)
15 | return encode.boxed()
16 | }
17 |
18 | override fun decode(tokens: List): String {
19 | val intArray: IntArrayList = IntArrayList(tokens.size)
20 | tokens.forEach { intArray.add(it) }
21 | return encoding.decode(intArray)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/embedding/text/EnglishTextEmbeddingProvider.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.embedding.text
2 |
3 | import cc.unitmesh.nlp.embedding.Embedding
4 | import cc.unitmesh.nlp.embedding.EmbeddingProvider
5 |
6 | /**
7 | * Use this class to embed English text, which is tokenized by space.
8 | */
9 | class EnglishTextEmbeddingProvider : EmbeddingProvider {
10 | override fun embed(texts: List): List {
11 | return texts.map { text ->
12 | val tokens = tokenize(text)
13 | tokens.map {
14 | it.toByteArray().map(Byte::toDouble)
15 | }.flatten()
16 | }
17 | }
18 |
19 | private fun tokenize(chunk: String): List {
20 | return chunk.split(Regex("[^a-zA-Z0-9]")).filter(String::isNotBlank)
21 | }
22 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/similarity/JaccardSimilarity.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.similarity
2 |
3 | import cc.unitmesh.nlp.embedding.Embedding
4 |
5 | /**
6 | * Jaccard similarity implementation.
7 | * use for Code, like GitHub Copilot, JetBrains AI Assistant
8 | */
9 | class JaccardSimilarity : Similarity {
10 | override fun similarityScore(set1: Embedding, set2: Embedding): Double {
11 | val intersectionSize: Int = (set1 intersect set2).size
12 | val unionSize: Int = (set1 union set2).size
13 | return intersectionSize.toDouble() / unionSize.toDouble()
14 | }
15 |
16 | companion object {
17 | fun between(embedding: List, referenceEmbedding: List): Double {
18 | return JaccardSimilarity().similarityScore(embedding, referenceEmbedding)
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/similarity/RelevanceScore.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.similarity
2 |
3 |
4 | object RelevanceScore {
5 | fun fromCosineSimilarity(cosineSimilarity: Double): Double {
6 | return (cosineSimilarity + 1) / 2
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/similarity/Similarity.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.similarity
2 |
3 | import cc.unitmesh.nlp.embedding.Embedding
4 |
5 | interface Similarity {
6 | fun similarityScore(set1: Embedding, set2: Embedding) : Double
7 | }
8 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/similarity/SimilarityScore.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.similarity
2 |
3 | data class SimilarityScore(val key: String, val similarity: Double)
4 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/tokenizer/CodeNamingTokenizer.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.tokenizer
2 |
3 | import cc.unitmesh.nlp.tokenizer.regexp.RegexTokenizerOptions
4 | import cc.unitmesh.nlp.tokenizer.regexp.RegexpTokenizer
5 | import kotlin.collections.map
6 | import kotlin.text.lowercase
7 |
8 | class CodeNamingTokenizer(opts: RegexTokenizerOptions? = null) : RegexpTokenizer(opts) {
9 | init {
10 | whitespacePattern = Regex(
11 | "(?<=[a-z])(?=[A-Z])|" + // camelCase 分词
12 | "(?<=[A-Z])(?=[A-Z][a-z])|" + // PascalCase 分词
13 | "(?<=[A-Za-z])(?=[0-9])|" + // 字母和数字分词
14 | "(?<=[0-9])(?=[A-Za-z])|" + // 数字和字母分词
15 | "_+" // under_score 分词
16 | )
17 | }
18 |
19 | override fun tokenize(text: String): List {
20 | val results = whitespacePattern.split(text)
21 | return if (discardEmpty) {
22 | without(results, "", " ").map { it.lowercase() }
23 | } else {
24 | results.map { it.lowercase() }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/tokenizer/Tokenizer.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.tokenizer
2 |
3 | import kotlin.collections.first
4 | import kotlin.collections.last
5 | import kotlin.collections.lastIndex
6 |
7 | interface Tokenizer {
8 | fun tokenize(text: String): List
9 | open fun trim(array: MutableList): List {
10 | while (array.last() == "") {
11 | array.removeAt(array.lastIndex)
12 | }
13 |
14 | while (array.first() == "") {
15 | array.removeAt(0)
16 | }
17 |
18 | return array
19 | }
20 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/tokenizer/WordTokenizer.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.tokenizer
2 |
3 | import cc.unitmesh.nlp.tokenizer.regexp.RegexTokenizerOptions
4 | import cc.unitmesh.nlp.tokenizer.regexp.RegexpTokenizer
5 |
6 | class WordTokenizer(options: RegexTokenizerOptions? = null) : RegexpTokenizer(options) {
7 | init {
8 | whitespacePattern = Regex("[^A-Za-zА-Яа-я0-9_]+")
9 | }
10 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/nlp/tokenizer/regexp/RegexTokenizerOptions.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.tokenizer.regexp
2 |
3 | interface RegexTokenizerOptions {
4 | val pattern: Regex?
5 | val discardEmpty: Boolean
6 | val gaps: Boolean?
7 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/rag/document/DocumentOrder.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag.document
2 |
3 | object DocumentOrder {
4 |
5 | /**
6 | * Los in the middle reorder: the most relevant will be at the
7 | * middle of the list and more relevant elements at beginning / end.
8 | * See: https://arxiv.org/abs//2307.03172"""
9 | *
10 | * re-score codes by min in the middle, max in the beginning and end, for examples:
11 | * 0.6, 0.5, 0.4, 0.3, 0.2, 0.1 -> 0.6, 0.4, 0.2, 0.1, 0.3, 0.5
12 | */
13 | fun lostInMiddleReorder(documents: List>): List> {
14 | val reversedDocuments = documents.reversed()
15 | val reorderedResult = mutableListOf>()
16 |
17 | for ((index, value) in reversedDocuments.withIndex()) {
18 | if (index % 2 == 1) {
19 | reorderedResult.add(value)
20 | } else {
21 | reorderedResult.add(0, value)
22 | }
23 | }
24 |
25 | return reorderedResult
26 | }
27 |
28 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/rag/document/Metadata.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag.document
2 |
3 | typealias Metadata = Map
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/rag/loader/Loader.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag.loader
2 |
3 | import cc.unitmesh.rag.document.Document
4 | import cc.unitmesh.rag.splitter.TextSplitter
5 |
6 | interface Loader {
7 | fun load(): List
8 |
9 | fun load(textSplitter: TextSplitter): List
10 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/rag/memory/Memory.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag.memory
2 |
3 | interface Memory {
4 | fun getKeys(): List
5 |
6 | fun load(inputs: Map): Map
7 |
8 | fun save(inputs: Map, outputs: Map)
9 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/rag/retriever/Retriever.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag.retriever
2 |
3 | import cc.unitmesh.nlp.embedding.Embedding
4 | import cc.unitmesh.rag.document.Document
5 | import cc.unitmesh.rag.store.EmbeddingMatch
6 |
7 | interface Retriever {
8 | fun retrieve(query: Embedding): List>
9 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/rag/splitter/Splitter.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag.splitter
2 |
3 | import cc.unitmesh.rag.document.Document
4 | import java.util.function.Function
5 |
6 |
7 | interface Splitter : Function, List>
8 |
9 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/rag/store/EmbeddingMatch.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag.store
2 |
3 | import cc.unitmesh.nlp.embedding.Embedding
4 |
5 |
6 | data class EmbeddingMatch(
7 | val score: Double,
8 | val embeddingId: String,
9 | val embedding: Embedding,
10 | val embedded: Embedded,
11 | ) {
12 |
13 | }
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/template/PromptCompiler.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.template
2 |
3 | import com.google.gson.JsonElement
4 |
5 | interface PromptCompiler {
6 | /**
7 | * Appends a key-value pair to the existing data.
8 | *
9 | * @param key The key to append.
10 | * @param value The value to append.
11 | */
12 | fun append(key: String, value: Any)
13 | fun compile(templatePath: String, dataPath: String): String
14 | fun compile(templatePath: String, data: Map): String
15 |
16 | /**
17 | * Compiles the given template into a string representation.
18 | *
19 | * @param template the path of the template to be compiled
20 | * @return the compiled template as a string
21 | */
22 | fun compileToString(template: String): String
23 | fun compile(templatePath: String, element: JsonElement): String
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/cocoa-core/src/main/kotlin/cc/unitmesh/template/TemplateEngineType.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.template
2 |
3 | enum class TemplateEngineType {
4 | VELOCITY,
5 | }
--------------------------------------------------------------------------------
/cocoa-core/src/test/kotlin/cc/unitmesh/nlp/similarity/JaccardSimilarityTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.nlp.similarity
2 |
3 | import cc.unitmesh.nlp.similarity.JaccardSimilarity
4 | import org.junit.jupiter.api.Assertions.*
5 | import org.junit.jupiter.api.Test
6 |
7 | class JaccardSimilarityTest {
8 | @Test
9 | fun should_calculate_similarity_score() {
10 | val similarity = JaccardSimilarity()
11 | // given
12 | val a = listOf(1.0, 2.0, 3.0)
13 | val b = listOf(1.0, 2.0, 4.0)
14 |
15 | // when
16 | val score = similarity.similarityScore(a, b)
17 |
18 | // then
19 | assertEquals(0.5, score)
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/cocoa-core/src/test/kotlin/cc/unitmesh/rag/document/DocumentOrderTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag.document;
2 |
3 | import org.junit.jupiter.api.Assertions.*
4 | import org.junit.jupiter.api.Test
5 |
6 | class LostInMiddleReorderTest {
7 |
8 | @Test
9 | fun should_return_reordered_list() {
10 | // given
11 | val documents = listOf(
12 | Pair(0.6, "doc1"),
13 | Pair(0.5, "doc2"),
14 | Pair(0.4, "doc3"),
15 | Pair(0.3, "doc4"),
16 | Pair(0.2, "doc5"),
17 | Pair(0.1, "doc6")
18 | )
19 |
20 | // when
21 | val result = DocumentOrder.lostInMiddleReorder(documents)
22 |
23 | val expected = listOf(
24 | 0.5 to "doc2",
25 | 0.3 to "doc4",
26 | 0.1 to "doc6",
27 | 0.2 to "doc5",
28 | 0.4 to "doc3",
29 | 0.6 to "doc1"
30 | )
31 | assertEquals(expected, result)
32 | }
33 | }
--------------------------------------------------------------------------------
/cocoa-core/src/test/kotlin/cc/unitmesh/rag/splitter/CharacterTextSplitterTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag.splitter;
2 |
3 | import io.kotest.matchers.shouldBe
4 | import org.junit.jupiter.api.Test
5 |
6 | class CharacterTextSplitterTest {
7 |
8 | private val splitter = CharacterTextSplitter()
9 |
10 | @Test
11 | fun should_split_single_line() {
12 | val text = """paragraph 1
13 | |
14 | |paragraph 2
15 | |
16 | |paragraph 3
17 | """.trimMargin()
18 |
19 | val result = splitTextWithRegex(text, "\n\n", false)
20 |
21 | result.size shouldBe 3
22 | result shouldBe listOf("paragraph 1", "paragraph 2", "paragraph 3")
23 | }
24 |
25 | @Test
26 | fun should_split_multiple_paragraph() {
27 | val text = """paragraph 1
28 | |
29 | |paragraph 2
30 | |
31 | |paragraph 3
32 | """.trimMargin()
33 |
34 | val result = splitter.splitText(text)
35 |
36 | result[0] shouldBe text
37 | }
38 | }
--------------------------------------------------------------------------------
/code-modules/README.md:
--------------------------------------------------------------------------------
1 | # Code Modules
2 |
3 | - Code Language identify
4 | - Code Splitter
5 | - Git Differ
6 | - Git Commmit Message
7 |
--------------------------------------------------------------------------------
/code-modules/api-tool-parser/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 |
--------------------------------------------------------------------------------
/code-modules/api-tool-parser/README.md:
--------------------------------------------------------------------------------
1 | # API Processor
2 |
3 | Todos:
4 |
5 | - [x] API Parser
6 | - [x] Swagger
7 | - [ ] Split swagger to grouping
8 | - [x] Postman
9 | - [x] CLI for prompting
10 | - [x] API to Domains
11 | - [ ] Domain Knowledge Tree
12 | - [ ] Remove Version from API
13 |
--------------------------------------------------------------------------------
/code-modules/api-tool-parser/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | alias(libs.plugins.jvm)
4 | alias(libs.plugins.serialization)
5 | }
6 |
7 | repositories {
8 | mavenCentral()
9 | }
10 |
11 | dependencies {
12 | implementation(libs.clikt)
13 | implementation(libs.serialization.json)
14 | implementation(libs.archguard.analyser.openapi)
15 |
16 | // Logging
17 | implementation(libs.logging.slf4j.api)
18 | implementation(libs.logging.logback.classic)
19 |
20 | implementation(libs.bundles.markdown)
21 | implementation(libs.dotenv)
22 |
23 | // java parser
24 | implementation(libs.swagger.parser.v3)
25 |
26 | testImplementation(kotlin("test"))
27 |
28 | testImplementation(libs.bundles.test)
29 | }
30 |
31 | tasks.test {
32 | useJUnitPlatform()
33 | }
34 |
35 | kotlin {
36 | jvmToolchain(11)
37 | }
38 |
--------------------------------------------------------------------------------
/code-modules/api-tool-parser/src/main/kotlin/cc/unitmesh/processor/api/ApiProcessorDetector.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.processor.api
2 |
3 | import org.archguard.scanner.analyser.api.base.ApiProcessor
4 | import java.io.File
5 |
6 | @Deprecated("Use org.archguard.scanner.analyser.ApiProcessorDetector.detectApiProcessor instead")
7 | object ApiProcessorDetector {
8 | fun detectApiProcessor(file: File, withPostman: Boolean = false, postmanOnly: Boolean = false): ApiProcessor? {
9 | return org.archguard.scanner.analyser.ApiProcessorDetector.detectApiProcessor(file, withPostman, postmanOnly)
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/code-modules/api-tool-parser/src/main/resources/logback-test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | %-4relative [%thread] %-5level %logger{35} - %msg %n
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/code-modules/api-tool-parser/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/code-modules/api-tool-parser/src/test/kotlin/cc/unitmesh/processor/api/ApiProcessorDetectorTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.processor.api
2 |
3 | import io.kotest.matchers.shouldBe
4 | import org.archguard.scanner.analyser.api.openapi.OpenApiV3Processor
5 | import org.archguard.scanner.analyser.api.parser.PostmanProcessor
6 | import org.junit.jupiter.api.Test
7 | import java.io.File
8 |
9 | class ApiProcessorDetectorTest {
10 |
11 | @Test
12 | fun detectApiProcessor() {
13 | val file = File("src/test/resources/testsets/postman.json")
14 | val processor = ApiProcessorDetector.detectApiProcessor(file, true)!!
15 | processor.javaClass shouldBe PostmanProcessor::class.java
16 |
17 | // swagger-3.json
18 | val file2 = File("src/test/resources/testsets/swagger-3.json")
19 | val processor2 = ApiProcessorDetector.detectApiProcessor(file2, true)!!
20 | processor2.javaClass shouldBe OpenApiV3Processor::class.java
21 |
22 | // swagger-3.yaml
23 | val file3 = File("src/test/resources/testsets/swagger-3.yaml")
24 | val processor3 = ApiProcessorDetector.detectApiProcessor(file3, true)!!
25 | processor3.javaClass shouldBe OpenApiV3Processor::class.java
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/code-modules/code-language/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | java
4 | alias(libs.plugins.jvm)
5 | alias(libs.plugins.serialization)
6 | }
7 |
8 | dependencies {
9 | implementation(libs.serialization.json)
10 |
11 | implementation(libs.archguard.analyser.estimate)
12 |
13 | testImplementation(libs.bundles.test)
14 | testRuntimeOnly(libs.test.junit.engine)
15 | }
16 |
--------------------------------------------------------------------------------
/code-modules/code-splitter/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Ben Boyter
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/code-modules/code-splitter/README.md:
--------------------------------------------------------------------------------
1 | # Code Splitter
2 |
3 | the code based on [scc](https://github.com/boyter/scc)
4 |
5 | > Sloc, Cloc and Code: scc is a very fast accurate code counter with complexity calculations and COCOMO estimates
6 | > written in pure Go
7 |
8 | - [ ] SCC has some issues on `.gitignore`, we need to fix it.
9 |
10 | ## Resources
11 |
12 | [Polyglot Is the Fastest Code-counting Tool Available](http://blog.vmchale.com/article/polyglot-comparisons)
13 |
14 | License
15 | ---
16 |
17 | This code is distributed under the MIT license. See `LICENSE` in this directory.
18 |
--------------------------------------------------------------------------------
/code-modules/code-splitter/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | java
4 | alias(libs.plugins.jvm)
5 | alias(libs.plugins.serialization)
6 | }
7 |
8 | dependencies {
9 | implementation(projects.cocoaCore)
10 | implementation(libs.kotlin.stdlib)
11 | implementation(libs.serialization.json)
12 |
13 | implementation(libs.chapi.domain)
14 |
15 | testImplementation(libs.bundles.test)
16 | testRuntimeOnly(libs.test.junit.engine)
17 | }
18 |
--------------------------------------------------------------------------------
/code-modules/git-commit-message/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | java
4 | alias(libs.plugins.jvm)
5 | alias(libs.plugins.serialization)
6 | }
7 |
8 | dependencies {
9 | implementation(libs.kotlin.stdlib)
10 | implementation(libs.serialization.json)
11 | implementation(libs.logging.slf4j.api)
12 |
13 | testImplementation(libs.bundles.test)
14 | testRuntimeOnly(libs.test.junit.engine)
15 | }
16 |
--------------------------------------------------------------------------------
/code-modules/git-commit-message/src/main/kotlin/org/changelog/CommitBase.kt:
--------------------------------------------------------------------------------
1 | package org.changelog
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class CommitReference(
7 | val raw: String,
8 | val action: String? = null,
9 | val owner: String? = null,
10 | val repository: String? = null,
11 | val issue: String,
12 | val prefix: String,
13 | )
14 |
15 | @Serializable
16 | data class CommitNote(
17 | var title: String,
18 | var text: String,
19 | )
20 |
21 | @Serializable
22 | data class Commit(
23 | var merge: String? = null,
24 | var revert: Map? = null,
25 | var header: String? = null,
26 | var body: String? = null,
27 | var footer: String? = null,
28 | val notes: MutableList = mutableListOf(),
29 | val mentions: MutableList = mutableListOf(),
30 | val references: MutableList = mutableListOf(),
31 | var meta: MutableMap = mutableMapOf(),
32 | )
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/code-modules/git-commit-message/src/main/kotlin/org/changelog/LICENSE.md:
--------------------------------------------------------------------------------
1 | ### MIT License
2 |
3 | Copyright © [conventional-changelog team](https://github.com/conventional-changelog)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 | of the Software, and to permit persons to whom the Software is furnished to do
10 | so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/code-modules/git-commit-message/src/main/kotlin/org/changelog/ParserRegexes.kt:
--------------------------------------------------------------------------------
1 | package org.changelog
2 |
3 | class ParserRegexes(
4 | val notes: Regex,
5 | val referenceParts: Regex,
6 | val references: Regex,
7 | val mentions: Regex,
8 | )
--------------------------------------------------------------------------------
/code-modules/git-differ/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | application
4 | alias(libs.plugins.jvm)
5 | alias(libs.plugins.serialization)
6 | }
7 |
8 | dependencies {
9 | implementation(libs.serialization.json)
10 | implementation(libs.archguard.analyser.diffChanges)
11 |
12 | implementation(libs.chapi.domain)
13 |
14 | // should get the code data from language analyser
15 | implementation(libs.chapi.kotlin) {
16 | exclude(group = "com.ibm.icu", module = "icu4j")
17 | exclude(group = "org.jetbrains.kotlin", module = "kotlin-test-junit")
18 | }
19 | implementation(libs.chapi.java) {
20 | exclude(group = "com.ibm.icu", module = "icu4j")
21 | exclude(group = "org.jetbrains.kotlin", module = "kotlin-test-junit")
22 | }
23 |
24 | testImplementation(libs.logging.logback.classic)
25 |
26 | implementation(libs.jgit)
27 | testImplementation(libs.bundles.test)
28 | }
29 |
--------------------------------------------------------------------------------
/code-modules/git-differ/src/main/kotlin/cc/unitmesh/cf/code/ChangedLineCount.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.code
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class ChangedLineCount(
7 | val added: Int,
8 | val deleted: Int,
9 | )
--------------------------------------------------------------------------------
/code-modules/git-differ/src/main/kotlin/cc/unitmesh/cf/code/ChangedNode.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.code
2 |
3 | import kotlinx.serialization.Serializable
4 | import org.archguard.scanner.core.diffchanges.NodeRelation
5 |
6 | @Serializable
7 | class ChangedNode(
8 | val path: String,
9 | val packageName: String,
10 | val className: String,
11 | val relations: List,
12 | val code: String,
13 | /**
14 | * ignore imports, comments, blank lines
15 | */
16 | val keyAddLines: Int = 0,
17 | /**
18 | * ignore imports, comments, blank lines
19 | */
20 | val keyDeletedLines: Int = 0,
21 | ) {
22 |
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/code-modules/git-differ/src/main/kotlin/cc/unitmesh/cf/code/OptimizePatch.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.code
2 |
3 | import kotlinx.serialization.Serializable
4 | import org.eclipse.jgit.diff.DiffEntry
5 |
6 | @Serializable
7 | data class OptimizePatch(
8 | val changedLineCount: ChangedLineCount,
9 | val changeType: PatchChangeType,
10 | val content: String,
11 | val path: String,
12 | )
13 |
14 | /**
15 | * from [org.eclipse.jgit.diff.DiffEntry.ChangeType]
16 | */
17 | enum class PatchChangeType {
18 | ADD,
19 | MODIFY,
20 | DELETE,
21 | RENAME,
22 | COPY;
23 |
24 | companion object {
25 | fun from(changeType: DiffEntry.ChangeType): PatchChangeType {
26 | return when (changeType) {
27 | DiffEntry.ChangeType.ADD -> ADD
28 | DiffEntry.ChangeType.MODIFY -> MODIFY
29 | DiffEntry.ChangeType.DELETE -> DELETE
30 | DiffEntry.ChangeType.RENAME -> RENAME
31 | DiffEntry.ChangeType.COPY -> COPY
32 | }
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/code-modules/git-differ/src/main/kotlin/cc/unitmesh/cf/code/command/ExecListeners.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.code.command
2 |
3 | import org.slf4j.Logger
4 |
5 | interface ExecListeners {
6 | fun stdout(data: String) {}
7 | fun stderr(data: String) {}
8 | }
9 |
10 | class LoggerExecListeners(private val logger: Logger) : ExecListeners {
11 | override fun stdout(data: String) {
12 | logger.info(data)
13 | }
14 |
15 | override fun stderr(data: String) {
16 | logger.error(data)
17 | }
18 | }
19 |
20 | class StringListExecListeners(private var stdout: MutableList, private var stderr: MutableList) : ExecListeners {
21 | override fun stdout(data: String) {
22 | stdout += data
23 | }
24 |
25 | override fun stderr(data: String) {
26 | stderr += data
27 | }
28 | }
--------------------------------------------------------------------------------
/code-modules/git-differ/src/main/kotlin/cc/unitmesh/cf/code/command/OS.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.code.command
2 |
3 | enum class OS {
4 | WINDOWS, LINUX, MAC, SOLARIS
5 | }
6 |
7 | public fun getOS(): OS? {
8 | val os = System.getProperty("os.name").lowercase()
9 | return when {
10 | os.contains("win") -> {
11 | OS.WINDOWS
12 | }
13 | os.contains("nix") || os.contains("nux") || os.contains("aix") -> {
14 | OS.LINUX
15 | }
16 | os.contains("mac") -> {
17 | OS.MAC
18 | }
19 | os.contains("sunos") -> {
20 | OS.SOLARIS
21 | }
22 | else -> null
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/code-modules/git-differ/src/test/kotlin/cc/unitmesh/cf/code/GitCommandTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.code;
2 |
3 | import cc.unitmesh.cf.code.command.OS
4 | import cc.unitmesh.cf.code.command.getOS
5 | import io.kotest.matchers.shouldBe
6 | import org.junit.jupiter.api.Test
7 |
8 | class GitOutputTest {
9 |
10 | @Test
11 | fun should_return_latest_commit_hash() {
12 | val gitCommand = GitCommand()
13 |
14 | val hash = gitCommand.latestCommitHash()
15 | getOS()?.let { os ->
16 | when {
17 | os != OS.WINDOWS -> {
18 | hash.stdout.split("\n").size shouldBe 10
19 | }
20 | else -> {
21 | println(hash.stdout)
22 | // maybe WSL ?
23 | // hash.stdout.split("\r\n").size shouldBe 10
24 | }
25 | }
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/code-modules/git-differ/src/test/kotlin/cc/unitmesh/cf/code/command/CommandTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.code.command
2 |
3 | import io.kotest.matchers.shouldNotBe
4 | import org.junit.jupiter.api.Test
5 |
6 | class CommandTest {
7 | @Test
8 | fun `test command manager git`() {
9 | var stdout = ""
10 | val options = ExecOptions(
11 | cwd = ".",
12 | listeners = object : ExecListeners {
13 | override fun stdout(data: String) {
14 | stdout += data
15 | }
16 |
17 | override fun stderr(data: String) {
18 | println(data)
19 | }
20 | }
21 | )
22 |
23 | Command().exec("git", listOf("--version"), options)
24 | stdout shouldNotBe ""
25 | }
26 | }
--------------------------------------------------------------------------------
/code-modules/git-differ/src/test/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | UTF-8
5 |
6 | [SCANNER] %logger{36} %msg%n
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/docs-builder/README.md:
--------------------------------------------------------------------------------
1 | # Docs Helper
2 |
3 | > DocsHelper Will generate a docs folder with all the markdown files in the current directory.
4 |
5 | Analysis Step:
6 |
7 | 1. parse source code from PsiComment
8 | 2. parse `@SampleCode` from Test class
9 | 3. generate markdown file
10 |
11 | Additional feature
12 |
13 | 1. setup Git Hook
14 | 2. run Hook in GitHub Action and local
15 |
16 | ## LICENSE
17 |
18 | findKDoc.kt based on JetBrains' Kotlin Dokka code, which is released under the Apache License, Version 2.0.
19 | code psi based on Ktlint, which is released under the MIT License.
20 |
21 |
--------------------------------------------------------------------------------
/docs-builder/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | id("application")
4 | alias(libs.plugins.jvm)
5 | alias(libs.plugins.shadow)
6 | alias(libs.plugins.serialization)
7 | }
8 |
9 | dependencies {
10 | api("org.jetbrains.kotlin:kotlin-compiler:1.9.10")
11 |
12 | implementation(libs.clikt)
13 | implementation(libs.kotlin.reflect)
14 |
15 | implementation(libs.logging.logback.classic)
16 | implementation(libs.logging.kotlin)
17 |
18 | testImplementation(libs.bundles.test)
19 | }
20 |
21 | application {
22 | mainClass.set("cc.unitmesh.docs.RunnerKt")
23 | }
24 |
25 | tasks {
26 | shadowJar {
27 | manifest {
28 | attributes(Pair("Main-Class", "cc.unitmesh.docs.RunnerKt"))
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/docs-builder/src/main/kotlin/cc/unitmesh/docs/model/DocContent.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.docs.model
2 |
3 | import cc.unitmesh.docs.kdoc.KDocContent
4 | import cc.unitmesh.docs.sample.ClassSample
5 | import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
6 | import org.jetbrains.kotlin.psi.KtElement
7 |
8 | data class DocContent(
9 | val name: String,
10 | val content: String,
11 | val element: KtElement?,
12 | val sampleCode: ClassSample? = null,
13 | ) {
14 | companion object {
15 | fun fromKDoc(content: KDocContent, sampleCode: ClassSample? = null): DocContent {
16 | return DocContent(
17 | name = content.element?.name ?: "",
18 | content = content.sections.joinToString("\n", transform = KDocSection::getContent),
19 | element = content.element,
20 | sampleCode = sampleCode
21 | )
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/docs-builder/src/main/kotlin/cc/unitmesh/docs/model/RootDocContent.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.docs.model
2 |
3 | data class RootDocContent(
4 | val root: DocContent,
5 | val children: List,
6 | )
--------------------------------------------------------------------------------
/docs-builder/src/main/kotlin/cc/unitmesh/docs/render/Render.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.docs.render
2 |
3 | data class CustomJekyllFrontMatter(
4 | var title: String,
5 | val parent: String,
6 | val navOrder: Int,
7 | val permalink: String,
8 | ) {
9 | fun toMarkdown(): String {
10 | return """
11 | ---
12 | layout: default
13 | title: $title
14 | parent: $parent
15 | nav_order: $navOrder
16 | permalink: $permalink
17 | ---
18 |
19 | """.trimIndent()
20 | }
21 | }
--------------------------------------------------------------------------------
/docs-builder/src/main/kotlin/cc/unitmesh/docs/sample/ClassSample.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.docs.sample
2 |
3 |
4 | data class ClassSample(val nodeName: String, val samples: List = listOf())
--------------------------------------------------------------------------------
/docs-builder/src/main/kotlin/cc/unitmesh/docs/sample/FunctionSample.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.docs.sample
2 |
3 | data class FunctionSample(val name: String, val content: String, var code: String = "")
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | framework.unitmesh.cc
--------------------------------------------------------------------------------
/docs/dsl/dsl.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Domain Specific Language
4 | nav_order: 95
5 | has_children: true
6 | permalink: /dsl
7 | ---
8 |
--------------------------------------------------------------------------------
/docs/dsl/semantic-dsl.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: ExplainQuery Semantic DSL
4 | parent: Domain Specific Language
5 | nav_order: 2
6 | permalink: /dsl/semantic-query
7 | ---
8 |
9 | Semantic DSL 基于 [CoUnit](https://github.com/unit-mesh/co-unit) 中的 DSL 所创建的:
10 |
11 | 
12 |
13 | CoUnit 对应的参考来源为:
14 |
15 | - Bloop:[https://github.com/BloopAI/bloop](https://github.com/BloopAI/bloop)
16 | - HyDE doc:[Precise Zero-Shot Dense Retrieval without Relevance Labels](https://arxiv.org/abs/2212.10496)
17 |
18 | 示例代码如下:
19 |
20 | ```markdown
21 | englishQuery: query git path change count by system id
22 | originLanguageQuery: 通过 ID 查找 Git 代码库路径变更统计信息
23 | hypotheticalCode:
24 | ###kotlin
25 | @SqlQuery(
26 | "select system_id as systemId, line_count as lineCount, path, changes" +
27 | " from scm_path_change_count where system_id = :systemId"
28 | )
29 | fun findCountBySystemId(systemId: Long): List
30 | ###
31 | ```
32 |
33 |
--------------------------------------------------------------------------------
/docs/evaluation/evaluation.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Evaluation
4 | nav_order: 90
5 | has_children: true
6 | permalink: /docs/prompt
7 | ---
8 |
9 | {: .no_toc }
10 |
--------------------------------------------------------------------------------
/docs/faq.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: FAQ
4 | nav_order: 200
5 | permalink: /faq
6 | ---
7 |
8 | ## 413 Request Entity Too Large
9 |
10 | ### 问题
11 |
12 | ```bash
13 | [SCANNER] o.a.s.ctl.client.ArchGuardHttpClient process topic: class-items
14 | [SCANNER] o.a.s.ctl.client.ArchGuardHttpClient response status: 413
15 | response body:
16 | 413 Request Entity Too Large
17 |
18 | 413 Request Entity Too Large
19 |
nginx/1.22.1
20 |
21 |
22 | ```
23 |
24 | ### 解决方案
25 |
26 | 需要配置 Nginx 的 `client_max_body_size` 参数,否则会出现 413 的错误。
27 |
28 | 示例:
29 |
30 | ```nginx
31 | http {
32 | ...
33 | client_max_body_size 20m;
34 | ...
35 | }
36 | ```
37 |
38 | ## Server 模块包体积过大
39 |
40 | 模块比较大的模块:
41 |
42 | - SentenceTransformers,需要使用 OnnxRuntime 和 Tokenizer 模块,体积:80M+
43 | - Code Interpreters,需要使用 Kotlin 编译器,体积: ~70M+
44 |
--------------------------------------------------------------------------------
/docs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unit-mesh/choco-builder/fdd4d700f9dc04d0bdef3bbc41b8955804cad135/docs/favicon.ico
--------------------------------------------------------------------------------
/docs/modules/modules.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Modules
4 | nav_order: 55
5 | has_children: true
6 | permalink: /modules
7 | ---
8 |
9 | # 模块分为四类:
10 |
11 | - RAG 模块集
12 | - Document 解析、处理模块
13 | - Elasticsearch 检索模块
14 | - Pinecone 检索模块
15 | - Code 模块集
16 | - 代码分割模块
17 | - 代码解释器模块
18 | - LLM 模块
19 | - 本地向量化:Sentence Transformers
20 | - DSL 模块
21 | - Design DSL 解释器
22 |
--------------------------------------------------------------------------------
/docs/patterns/coordinate-model.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: 协作小模型
4 | parent: Patterns
5 | nav_order: 100
6 | ---
7 |
8 | ## 示例应用
9 |
10 | Intellij IDEA
11 |
12 | ## 相关研究
13 |
14 | ### [Small Language Models Fine-tuned to Coordinate Larger Language Models improve Complex Reasoning](https://arxiv.org/abs/2310.18338)
15 |
16 | >
17 | 本文介绍了一种名为DaSLaM的模块化方法,用于解决复杂的多步推理问题。该方法使用一个较小的语言模型作为分解生成器,将问题分解为需要更少推理步骤的子问题,
18 | 并使用一个求解器回答这些子问题。该方法不受求解器规模的限制,可以与不同规模的求解器一起使用。实验结果表明,使用该方法可以获得与规模更大的语言模型
19 | 相当甚至更好的性能。
20 |
21 | 中文翻译:[微调小模型和大模型协作提高复杂推理能力](https://mp.weixin.qq.com/s/UkBpbz0VdJEfP1XJgpImWw)
22 |
--------------------------------------------------------------------------------
/docs/patterns/flare.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: 前瞻性主动检索增强生成:FLARE
4 | parent: Patterns
5 | nav_order: 2
6 | ---
7 |
8 | 前瞻性主动检索增强生成(FLARE)
9 |
10 | 
11 |
12 | > FLARE(Forward-Looking Active REtrieval augmented generation) 是一种通用的检索增强生成方法,它通过对即将到来的句子进行预测来主动决定何时以及何时检索,
13 | > 以预测未来内容,并将其用作查询以检索相关文档,如果句子包含置信度较低的标记。
14 |
15 |
16 | FLARE(Forward-Looking Active REtrieval augmented generation)的主要目标是提高自然语言处理模型的生成能力,使其能够在生成文本时主动获取和利用外部信息,以提供更准确、全面和信息丰富的答案。以下是FLARE的一些主要目标和优势:
17 |
18 | 1. **主动检索和利用外部信息:** FLARE可以主动识别模型不确定的标记,并自动检索相关文档,以获取有关这些标记的信息。这有助于模型获取丰富的上下文信息,从而提高了生成文本的质量和准确性。
19 | 2. **提高生成文本的一致性:** FLARE可以帮助生成模型避免生成不一致或错误的信息,因为它会在需要时检索准确的信息来支持文本生成。
20 | 3. **扩展模型的知识和能力:** FLARE使模型能够利用外部知识库、文档或资源,从而扩展了模型的知识和能力,使其能够回答更广泛的问题。
21 | 4. **提高生成文本的可解释性:** FLARE可以使模型的生成过程更具可解释性,因为它明确地显示了模型何时以及为什么选择检索外部信息。这有助于用户理解模型的工作方式。
22 | 5. **应对模型的不确定性:** FLARE有助于处理模型在生成文本时的不确定性,因为它可以在模型不确定的情况下及时获取支持性信息,从而提高了生成的可靠性。
23 |
24 | 总之,FLARE旨在增强生成模型的能力,使其更智能地获取和利用外部信息,从而提高生成文本的质量、准确性和可用性。这对于各种自然语言处理任务和应用程序都具有潜在的益处,如问答系统、文本摘要、翻译等。
25 |
26 | ## 相关资源
27 |
28 | LangChain 示例:[Retrieve as you generate with FLARE](https://python.langchain.com/docs/use_cases/question_answering/how_to/flare)
29 |
30 |
31 |
--------------------------------------------------------------------------------
/docs/patterns/patterns.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Patterns
4 | nav_order: 85
5 | has_children: true
6 | permalink: /patterns
7 | ---
8 |
9 | {: .no_toc }
10 |
--------------------------------------------------------------------------------
/docs/patterns/pre-built-embedding.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: 预构建 Embedding Indexes
4 | parent: Patterns
5 | nav_order: 99
6 | ---
7 |
8 | 预构建 Embedding Indexes 是一种向量化索引数据,即将系统的一些内置的知识向量化,并可以以文件的形式进行导出和下载,以便于用户在本地进行使用。
9 |
10 | 示例:JetBrains AI Assistants 中的预定义 Action 等构建为 Embedding Indexes,减少了用户的本地工作量。
11 |
12 | 示例文件:[semantic-text-search-0.0.3.jar](https://packages.jetbrains.team/maven/p/ml-search-everywhere/local-models/org/jetbrains/intellij/searcheverywhereMl/semantics/semantic-text-search/0.0.3/semantic-text-search-0.0.3.jar)
13 |
14 | ```bash
15 | semantic-text-search-0.0.3
16 | ├── META-INF
17 | │ └── MANIFEST.MF
18 | ├── actions
19 | │ ├── embeddings.bin # 预构建的 Embedding Indexes
20 | │ └── ids.json # 预构建的 Embedding Indexes 的 ID
21 | └── models
22 | ├── dan-bert-tiny
23 | │ ├── encoder
24 | │ │ └── tokenizer_config.json
25 | │ └── optimized
26 | │ └── dan_optimized_fp16.onnx
27 | └── encoder
28 | └── bert-base-uncased.txt
29 | ```
30 |
--------------------------------------------------------------------------------
/docs/patterns/query-to-doc.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: 查询改写,提升匹配度
4 | parent: Patterns
5 | nav_order: 1
6 | ---
7 |
8 | > 查询改写(Query Rewriting,或称为查询扩展Query Expansion)。查询改写的应用方式是对原始 Query 拓展出与用户需求关联度高的改写词,
9 | > 多个改写词与用户搜索词一起做检索,从而用更好的表述,帮用户搜到更多符合需求的商户、商品和服务。
10 |
11 | 业内案例:[美团搜索中查询改写技术的探索与实践](https://tech.meituan.com/2022/02/17/exploration-and-practice-of-query-rewriting-in-meituan-search.html)
12 |
13 | 图示为美团向量召回技术架构:
14 |
15 | 
16 |
17 | ## 其它示例
18 |
19 | TODOS:
20 |
21 | ## 相关资源
22 |
23 | - [Query Expansion by Prompting Large Language Models](https://arxiv.org/abs/2305.03653)
24 | - [Query2doc: Query Expansion with Large Language Models](https://arxiv.org/abs/2303.07678)
25 |
26 | 中文:
27 |
28 | - 《[Query 理解和语义召回在知乎搜索中的应用](https://github.com/PO-VINCENT/nlp_papers/blob/main/Query%20%E7%90%86%E8%A7%A3%E5%92%8C%E8%AF%AD%E4%B9%89%E5%8F%AC%E5%9B%9E%E5%9C%A8%E7%9F%A5%E4%B9%8E%E6%90%9C%E7%B4%A2%E4%B8%AD%E7%9A%84%E5%BA%94%E7%94%A8.pdf)》
29 | - 《[通过提示大型语言模型实现查询扩展](https://zhuanlan.zhihu.com/p/633406099)》
30 |
31 |
--------------------------------------------------------------------------------
/docs/prompt-script/template-datasource.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: TemplateDatasource
4 | parent: Prompt Script
5 | nav_order: 11
6 | permalink: /prompt-script/template-datasource
7 | ---
8 |
9 | {: .warning }
10 | Automatically generated documentation; use the command `./gradlew :docs-builder:run` and update comments in the source code to reflect changes.
11 |
12 | # TemplateDatasource
13 |
14 | > TemplateDatasource is the job's template datasource config, which will be used for render template.
15 | The datasource can be a file, a directory or an http url, or a string, which be auto loaded by extension.
16 | For example:
17 |
18 | ```yaml
19 | template-datasource:
20 | - type: file
21 | value: datasource.json
22 | ```
23 |
24 | We will load the datasource.json file as the template datasource.
25 |
26 | ## File
27 |
28 | File is a file datasource, which will load data from a file.
29 |
30 |
--------------------------------------------------------------------------------
/docs/prompt/frontend/frontend-clarify.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: UI 设计 - Clarify 阶段
4 | parent: Prompt Sample
5 | nav_order: 1
6 | ---
7 |
8 | 你是一个专业的前端技术咨询师(Advisor),职责是帮助开发人员用户收集和分析需求。
9 |
10 | - 你必须使用中文和用户沟通。
11 | - 当用户问你问题时,你必须帮助用户明确他们的需求。
12 | - 当用户问你是谁时,你必须回答:我是一个专业的前端技术专家,职责是帮助用户编写前端代码。
13 | - 当用户的问题比较发散、不明确,请和用户沟通,收集更多的信息,帮助用户明确他们的需求。
14 |
15 | 已有布局方式如下:
16 |
17 | 流式布局,浮动布局,栅格布局,弹性盒子布局
18 |
19 | 已有组件如下:
20 |
21 | 面包屑,卡片,对话框,分页,标签
22 |
23 | 请严格用以下格式输出:
24 | - 思考:是否包含了用户故事和布局信息,如果明确请结束询问,如果不明确,请继续询问。
25 | - 行动:为"CONTINUE"或者"FINISH"
26 | - 询问:想继续询问的问题
27 | - 最终输出:完整的问题
28 | - 思考-行动-询问可以循环数次,直到最终输出
29 |
30 | 示例一:
31 | - 输入:编写一个登录页面
32 | - 输出:
33 | - 思考:用户想要编写登录页面,但是没有说明布局方式,应该继续询问。
34 | - 行动:CONTINUE
35 | - 询问:您想要什么布局方式?
36 |
37 | 示例二:
38 | - 输入:编写一个栅格布局的登录页面
39 | - 输出:
40 | - 思考:用户想要编写栅格布局的登录页面,其中栅格布局是布局方式,登录页面是用户故事,已经明确,应该结束询问。
41 | - 行动:FINISH
42 | - 最终输出:编写一个栅格布局的登录页面
43 |
44 | 请严格按格式输出!
45 | 以下是您和当前用户的交互历史:
46 |
47 | 输入:使用编写一个用户个人信息页
48 |
--------------------------------------------------------------------------------
/docs/prompt/prompt.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Prompt Sample
4 | nav_order: 100
5 | has_children: true
6 | permalink: /docs/prompt
7 | ---
8 |
9 | Prompt Sample provides a sample of a prompt for explaining the use of the prompt.
10 |
11 | {: .no_toc }
12 |
--------------------------------------------------------------------------------
/docs/prompt/qa/qa-design.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Testcase Design
4 | parent: Prompt Sample
5 | nav_order: 12
6 | ---
7 |
8 | 你是一个资深的质量工程师(Quality assurance)教练,职责是根据多个不同级别的 QA 测试用例,构造出更合理的测试用例。
9 |
10 | 资深 QA 写的测试用例集:
11 |
12 | ```testcases
13 | 测试目标:
14 | - 验证管理员可以成功将商品上架到系统,并能显示已上架的商品。
15 | - 验证系统能正确处理商品的上架日期和状态。
16 | - 验证系统能够正确处理商品上架的价格和库存信息。
17 | - 验证系统能够正确处理上架商品的图片上传和显示。
18 | - 验证系统能够正确处理上架商品的分类和标签。
19 | - 验证系统能够正确计算和显示上架商品的销售统计信息。
20 | - 验证系统能够正确处理上架商品的描述和详情信息。
21 | - 验证系统能够正确处理上架商品的规格和属性信息。
22 | - 验证系统能够正确处理上架商品的促销和优惠信息。
23 | - 验证系统能够正确处理上架商品的配送和物流信息。
24 | - 验证系统能够正确处理上架商品的售后和退款信息。
25 | ```
26 |
27 | 初级 QA 写的测试用例集
28 |
29 | ```testcases
30 | 测试目标:
31 | - 验证管理员可以成功将商品上架到系统,并能显示已上架的商品。
32 | - 验证系统能正确处理商品的上架日期和状态。
33 | - 验证系统能够正确处理商品上架的价格和库存信息。
34 | - 验证系统能够正确处理上架商品的图片上传和显示。
35 | - 验证系统能够正确处理上架商品的分类和标签。
36 | - 验证系统能够正确计算和显示上架商品的销售统计信息。
37 | - 验证系统能够正确处理商品上架时的特殊字符和边界条件。
38 | - 验证系统能够正确处理商品上架时的重复上架和重复分类情况。
39 | - 验证系统能够正确处理商品上架时的价格和库存的边界条件。
40 | - 验证系统能够正确处理上架商品的特殊标签和分类。
41 | - 验证系统能够正确处理上架商品时的图片格式和大小限制。
42 | ```
43 |
44 | 最后,你需要将这些测试用例,整理成一个测试计划,使用 markdown 表格输出。
45 | markdown 表格格式如下:测试要点,案例名称,案例描述,测试数据,测试步骤,预期结果,案例,属性,案例,等级,执行,方式,执行结果
46 |
--------------------------------------------------------------------------------
/docs/rag-script/prompt-text.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: PromptText
4 | parent: RAG Script
5 | nav_order: 10
6 | permalink: /rag-script/prompt-text
7 | ---
8 |
9 | {: .warning }
10 | Automatically generated documentation; use the command `./gradlew :docs-builder:run` and update comments in the source code to reflect changes.
11 |
12 | # PromptText
13 |
14 | > PromptText is a DSL for writing a prompt, will generate Markdown text.
15 | - codeblock, will generate a codeblock starts with ```language
16 | - paragraph, will generate a paragraph
17 | - list, will generate a list
18 | - linebreak, will generate a linebreak
19 |
20 | Sample: PromptScript
21 |
22 | ```kotlin
23 | prompt {
24 | paragraph("Hello World")
25 | codeblock("kotlin") {
26 | "println(\"Hello World\")"
27 | }
28 | list(ListType.Unordered) {
29 | listOf("Hello", "World")
30 | }
31 | }
32 | ```
33 |
34 | ## list
35 |
36 | type can be unordered, ordered, or checked
37 |
38 |
--------------------------------------------------------------------------------
/docs/rag/data-manage.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Data Management
4 | parent: Retrieval Augmented Generation
5 | nav_order: 1
6 | ---
7 |
8 | Tech Stacks: [DataFrame](https://github.com/Kotlin/dataframe) ?
9 |
10 | ## Data loader
11 |
12 | TODO
13 |
14 | ## Data Preprocessing
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/docs/rag/embedding-model.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Embedding Model
4 | parent: Retrieval Augmented Generation
5 | nav_order: 80
6 | ---
7 |
8 | [Vector Embedding](https://guangzhengli.com/blog/zh/vector-database/) 是由 AI 模型(例如大型语言模型
9 | LLM)生成的,它会根据不同的算法生成高维度的向量数据,代表着数据的不同特征,这些特征代表了数据的不同维度。
10 | 例如,对于文本,这些特征可能包括词汇、语法、语义、情感、情绪、主题、上下文等。 对于音频,这些特征可能包括音调、节奏、音高、音色、音量、语音、音乐等。
11 |
12 | 开放模型:
13 |
14 | - [FlagEmbedding](https://github.com/FlagOpen/FlagEmbedding)/智源 BGE(BAAI General Embedding,是一款用于生成语义向量的开源模型,特别适用于中英文语义检索、推荐系统、数据挖掘等领域。
15 | - [M3E](https://huggingface.co/moka-ai/m3e-base)(Moka Massive Mixed Embedding)
16 | - [all-MiniLM-L6-v2](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2)
17 |
18 |
--------------------------------------------------------------------------------
/docs/workflow/workflow.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Workflow
4 | nav_order: 3
5 | has_children: true
6 | permalink: /docs/workflow
7 | ---
8 |
9 | {: .no_toc }
10 |
--------------------------------------------------------------------------------
/dsl/design/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | java
4 | id("antlr")
5 | alias(libs.plugins.jvm)
6 | alias(libs.plugins.serialization)
7 | }
8 |
9 | dependencies {
10 | antlr("org.antlr:antlr4:4.13.1")
11 |
12 | implementation("org.antlr:antlr4:4.13.1")
13 | implementation("org.antlr:antlr4-runtime:4.13.1")
14 |
15 | implementation(libs.kotlin.stdlib)
16 | implementation(libs.serialization.json)
17 |
18 | testImplementation(libs.bundles.test)
19 | testRuntimeOnly(libs.test.junit.engine)
20 | }
21 |
22 | sourceSets.main {
23 | java.srcDirs("${project.buildDir}/generated-src")
24 | }
25 |
26 | tasks.generateGrammarSource {
27 | maxHeapSize = "64m"
28 | arguments = arguments + listOf("-package", "cc.unitmesh.dsl") + listOf("-visitor", "-long-messages")
29 | outputDirectory = file("${project.buildDir}/generated-src/cc/unitmesh/dsl")
30 | }
31 |
32 | tasks.withType {
33 |
34 | }
35 |
36 | tasks.withType().configureEach {
37 | dependsOn(tasks.withType())
38 | }
39 |
40 | tasks.named("compileKotlin") {
41 | dependsOn(tasks.withType())
42 | }
--------------------------------------------------------------------------------
/dsl/design/src/main/kotlin/cc/unitmesh/dsl/design/DesignDsl.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.dsl.design
2 |
3 | import cc.unitmesh.dsl.DesignLexer
4 | import cc.unitmesh.dsl.DesignParser
5 | import org.antlr.v4.runtime.CharStreams
6 | import org.antlr.v4.runtime.CommonTokenStream
7 | import org.antlr.v4.runtime.tree.ParseTreeWalker
8 |
9 | class DesignDsl {
10 | fun analysis(design: String): DesignInformation {
11 | val context = this.parse(design).start()
12 | val listener = DesignAppListener()
13 |
14 | ParseTreeWalker().walk(listener, context)
15 |
16 | return listener.buildDesign()
17 | }
18 |
19 | fun parse(str: String): DesignParser {
20 | val fromString = CharStreams.fromString(str)
21 | val lexer = DesignLexer (fromString)
22 | val tokenStream = CommonTokenStream(lexer)
23 | return DesignParser(tokenStream)
24 | }
25 | }
--------------------------------------------------------------------------------
/examples/prompt-script/.gitignore:
--------------------------------------------------------------------------------
1 | *.txt
2 | openai-connection.yml
--------------------------------------------------------------------------------
/examples/prompt-script/code-complete.open-ai.vm:
--------------------------------------------------------------------------------
1 | ```system```
2 | You are a helpful assistant. You should use Json to answer User's question.
3 |
4 | #foreach ($item in $chat_history)
5 | user:
6 | ${item.inputs.question}
7 | assistant:
8 | ${item.outputs.answer}
9 | #end
10 |
11 | ```user```
12 | ${question}
13 |
--------------------------------------------------------------------------------
/examples/prompt-script/connection.yml:
--------------------------------------------------------------------------------
1 | name: mock_response
2 | type: MockLlm
3 | configs:
4 | api-response: "{\"text\": \"this is a mock resource\"}"
5 |
--------------------------------------------------------------------------------
/examples/prompt-script/datasource.json:
--------------------------------------------------------------------------------
1 | {
2 | "question": "最流行的前端框架是?",
3 | "chat_history": [
4 | {
5 | "inputs": {
6 | "role": "user",
7 | "question": "中国的首都是哪里?"
8 | },
9 | "outputs": {
10 | "role": "assistant",
11 | "answer": "{\"text\":\"北京\"}"
12 | }
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/examples/prompt-script/prompt.unit-mesh.yml:
--------------------------------------------------------------------------------
1 | name: "Open AI Verifier"
2 | description: "Verify Open AI's LLM"
3 |
4 | jobs:
5 | prompt-evaluate: # job name should be unique for each job
6 | description: "Evaluate prompt with different parameters"
7 | connection: connection.yml
8 | template: code-complete.open-ai.vm # auto choice template by extension
9 | template-datasource:
10 | - type: file
11 | value: datasource.json
12 |
13 | strategy:
14 | - type: connection
15 | value:
16 | - type: range
17 | key: temperature
18 | range: 0.7~1.0
19 | step: 0.1
20 | - type: repeat
21 | value: 3
22 |
23 | validate: # optional
24 | - type: json-path
25 | value: $.id
26 | - type: string
27 | value: output.length > 300
28 |
--------------------------------------------------------------------------------
/examples/rag-script/english-text.main.kts:
--------------------------------------------------------------------------------
1 | @file:DependsOn("cc.unitmesh:rag-script:0.3.6")
2 |
3 | import cc.unitmesh.rag.*
4 |
5 | rag {
6 | indexing {
7 | val chunks = text("fun main(args: Array) {\n println(\"Hello, World!\")\n}").split()
8 | store.indexing(chunks)
9 | }
10 |
11 | querying {
12 | store.findRelevant("Hello World").also {
13 | println(it)
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/examples/rag-script/sentence-transformers.main.kts:
--------------------------------------------------------------------------------
1 | @file:DependsOn("cc.unitmesh:rag-script:0.3.6")
2 |
3 | import cc.unitmesh.rag.*
4 |
5 | rag("code") {
6 | llm = LlmConnector(LlmType.OpenAI)
7 | embedding = EmbeddingEngine(EngineType.SentenceTransformers)
8 | store = Store(StoreType.Memory)
9 |
10 | indexing {
11 | document("filename.txt").split().also {
12 | store.indexing(it)
13 | }
14 | }
15 |
16 | querying {
17 | store.findRelevant("workflow dsl design ").also {
18 | println(it)
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unit-mesh/choco-builder/fdd4d700f9dc04d0bdef3bbc41b8955804cad135/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/llm-modules/connection/README.md:
--------------------------------------------------------------------------------
1 | # Connection Manager [TODO]
2 |
3 | > connection manager is a module for managing connections to the LLM.
4 |
5 | 在 Promptflow 中,Connection 是指连接到 API 的一种方式,例如,连接到数据库、连接到文件系统、连接到远程服务等。
6 |
7 | - LLM API:诸如于 OpenAI API、HuggingFace API 等。
8 | - Store,以 VectorStore 为主,配合传统数据库,如 MySQL、PostgreSQL、MongoDB 等。
9 | - Tool API:诸如于 SerpAPI、Google Search API 等。
10 |
--------------------------------------------------------------------------------
/llm-modules/connection/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(libs.plugins.jvm)
3 | alias(libs.plugins.serialization)
4 | }
5 |
6 | dependencies {
7 | implementation(projects.llmModules.openai)
8 |
9 | implementation(libs.serialization.json)
10 | implementation(libs.rxjava3)
11 |
12 | testImplementation(libs.bundles.test)
13 | testRuntimeOnly(libs.test.junit.engine)
14 | }
15 |
--------------------------------------------------------------------------------
/llm-modules/connection/src/main/kotlin/cc/unitmesh/connection/MockLlmConnection.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.connection
2 |
3 | /**
4 | * MockLlmConnection is a mock connection for testing in local.
5 | * For example:
6 | * ```yaml
7 | * name: mock_response
8 | * type: MockLlm
9 | *
10 | * configs:
11 | * api-response: "{\"text\": \"this is a mock resource\"}"
12 | * ```
13 | */
14 | class MockLlmConnection(val response: String) : ConnectionConfig(
15 | name = "mock",
16 | type = ConnectionType.MockLlm
17 | ) {}
--------------------------------------------------------------------------------
/llm-modules/connection/src/main/kotlin/cc/unitmesh/connection/OpenAiConnection.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.connection
2 |
3 | /**
4 | * OpenAiConnection is a connection for OpenAI API.
5 | * For example:
6 | * ```yaml
7 | * name: open_ai_connection
8 | * type: OpenAI
9 | * secrets:
10 | * api-key: ak-xxxx
11 | *```
12 | *
13 | * If you are using proxyed OpenAI API, you can set the api-host in configs.
14 | *
15 | * ```yaml
16 | * name: open_ai_connection
17 | * type: OpenAI
18 | * configs:
19 | * api-host: https://api.aios.chat/
20 | * secrets:
21 | * api-key: ak-xxxx
22 | * ```
23 | */
24 | data class OpenAiConnection(
25 | val apiHost: String,
26 | val apiKey: String,
27 | ) : ConnectionConfig(
28 | name = "openai",
29 | type = ConnectionType.OpenAI
30 | ) {
31 |
32 | }
33 |
34 | data class AzureOpenAiConnection(
35 | val apiHost: String,
36 | val apiKey: String,
37 | ) : ConnectionConfig(
38 | name = "azure-openai",
39 | type = ConnectionType.AzureOpenAI
40 | ) {
41 |
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/llm-modules/connection/src/test/resources/connection/azure_openai.yml:
--------------------------------------------------------------------------------
1 | $schema: schemas/AzureOpenAIConnection.schema.json
2 | name: open_ai_connection
3 | type: AzureOpenAI
4 | configs:
5 | api-base: "aoai-api-endpoint"
6 | secrets:
7 | api-key: ""
8 | api-type: "azure"
9 |
--------------------------------------------------------------------------------
/llm-modules/connection/src/test/resources/connection/custom.yml:
--------------------------------------------------------------------------------
1 | $schema: schemas/CustomConnection.schema.json
2 | name: custom_connection
3 | type: custom
4 | secrets: # required
5 | api-key: ""
6 | configs:
7 | key1: "test1"
8 |
--------------------------------------------------------------------------------
/llm-modules/connection/src/test/resources/connection/openai.yml:
--------------------------------------------------------------------------------
1 | $schema: schemas/OpenAIConnection.schema.json
2 | name: open_ai_connection
3 | type: OpenAI
4 | configs:
5 | api-host: "aoai-api-endpoint.phodal.com"
6 | organization: "" # optional
7 | secrets:
8 | api-key: ""
9 | api-type: "azure"
10 |
--------------------------------------------------------------------------------
/llm-modules/connection/src/test/resources/connection/serp.yml:
--------------------------------------------------------------------------------
1 | $schema: schemas/SerpConnection.schema.json
2 | name: serp_connection
3 | type: serp
4 | secrets:
5 | api-key: ""
6 |
--------------------------------------------------------------------------------
/llm-modules/dan-bert-tiny/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | alias(libs.plugins.jvm)
4 | alias(libs.plugins.serialization)
5 | }
6 |
7 | dependencies {
8 | implementation(libs.kotlin.stdlib)
9 | implementation(libs.coroutines.core)
10 |
11 | testImplementation(libs.bundles.test)
12 | testRuntimeOnly(libs.test.junit.engine)
13 | }
14 |
--------------------------------------------------------------------------------
/llm-modules/dan-bert-tiny/src/main/resources/dan_optimized_fp16.onnx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unit-mesh/choco-builder/fdd4d700f9dc04d0bdef3bbc41b8955804cad135/llm-modules/dan-bert-tiny/src/main/resources/dan_optimized_fp16.onnx
--------------------------------------------------------------------------------
/llm-modules/dan-bert-tiny/src/main/resources/tokenizer_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "do_lower_case": true,
3 | "unk_token": "[UNK]",
4 | "sep_token": "[SEP]",
5 | "pad_token": "[PAD]",
6 | "cls_token": "[CLS]",
7 | "mask_token": "[MASK]",
8 | "clean_up_tokenization_spaces": true,
9 | "tokenize_chinese_chars": true,
10 | "strip_accents": null,
11 | "special_tokens_map_file": null,
12 | "do_basic_tokenize": true,
13 | "never_split": null,
14 | "tokenizer_class": "BertTokenizer",
15 | "model_max_length": 512
16 | }
17 |
--------------------------------------------------------------------------------
/llm-modules/local-embedding/README.md:
--------------------------------------------------------------------------------
1 | # Local Embedding
2 |
--------------------------------------------------------------------------------
/llm-modules/local-embedding/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | alias(libs.plugins.jvm)
4 | alias(libs.plugins.serialization)
5 | }
6 |
7 | dependencies {
8 | implementation(libs.kotlin.stdlib)
9 | implementation(libs.coroutines.core)
10 |
11 | implementation(libs.onnxruntime)
12 | implementation(libs.huggingface.tokenizers) {
13 | exclude(group = "org.slf4j", module = "slf4j-api")
14 | }
15 |
16 | testImplementation(libs.bundles.test)
17 | testImplementation(projects.llmModules.danBertTiny)
18 | testRuntimeOnly(libs.test.junit.engine)
19 | }
20 |
--------------------------------------------------------------------------------
/llm-modules/local-embedding/src/main/kotlin/cc/unitmesh/cf/Embedding.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf
2 |
3 | import ai.djl.huggingface.tokenizers.HuggingFaceTokenizer
4 |
5 | interface Embedding {
6 | fun getTokenizer(): HuggingFaceTokenizer
7 | fun embed(input: String): List
8 | }
--------------------------------------------------------------------------------
/llm-modules/local-embedding/src/main/resources/model/model.onnx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unit-mesh/choco-builder/fdd4d700f9dc04d0bdef3bbc41b8955804cad135/llm-modules/local-embedding/src/main/resources/model/model.onnx
--------------------------------------------------------------------------------
/llm-modules/local-embedding/src/main/resources/model/special_tokens_map.json:
--------------------------------------------------------------------------------
1 | {
2 | "cls_token": "[CLS]",
3 | "mask_token": "[MASK]",
4 | "pad_token": "[PAD]",
5 | "sep_token": "[SEP]",
6 | "unk_token": "[UNK]"
7 | }
8 |
--------------------------------------------------------------------------------
/llm-modules/local-embedding/src/main/resources/model/tokenizer_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "cls_token": "[CLS]",
3 | "do_basic_tokenize": true,
4 | "do_lower_case": true,
5 | "mask_token": "[MASK]",
6 | "model_max_length": 512,
7 | "name_or_path": "sentence-transformers/all-MiniLM-L6-v2",
8 | "never_split": null,
9 | "pad_token": "[PAD]",
10 | "sep_token": "[SEP]",
11 | "special_tokens_map_file": "/Users/gabriel/.cache/huggingface/hub/models--sentence-transformers--all-MiniLM-L6-v2/snapshots/7dbbc90392e2f80f3d3c277d6e90027e55de9125/special_tokens_map.json",
12 | "strip_accents": null,
13 | "tokenize_chinese_chars": true,
14 | "tokenizer_class": "BertTokenizer",
15 | "unk_token": "[UNK]"
16 | }
17 |
--------------------------------------------------------------------------------
/llm-modules/openai/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(libs.plugins.jvm)
3 | alias(libs.plugins.serialization)
4 | }
5 |
6 | dependencies {
7 | implementation(projects.cocoaCore)
8 | implementation(libs.rxjava3)
9 | implementation(libs.serialization.json)
10 |
11 | implementation(libs.bundles.openai)
12 | implementation(libs.coroutines.core)
13 | implementation(libs.bundles.jackson)
14 |
15 | testImplementation(libs.bundles.test)
16 | testRuntimeOnly(libs.test.junit.engine)
17 | }
18 |
--------------------------------------------------------------------------------
/llm-modules/openai/src/main/kotlin/cc/unitmesh/azure/AzureOpenAIDto.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.azure
2 |
3 | import com.theokanning.openai.completion.chat.ChatMessage
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class SimpleOpenAIFormat(val role: String, val content: String) {
8 | companion object {
9 | fun fromChatMessage(message: ChatMessage): SimpleOpenAIFormat {
10 | return SimpleOpenAIFormat(message.role, message.content)
11 | }
12 | }
13 | }
14 |
15 | @Serializable
16 | data class SimpleOpenAIBody(val messages: List, val temperature: Double, val stream: Boolean)
--------------------------------------------------------------------------------
/llm-modules/openai/src/main/kotlin/cc/unitmesh/openai/MsgConverter.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.openai
2 |
3 | import cc.unitmesh.cf.core.llms.LlmMsg
4 | import com.theokanning.openai.completion.chat.ChatCompletionChoice
5 |
6 | private fun ChatCompletionChoice.toAbstract(): LlmMsg.ChatChoice {
7 | return LlmMsg.ChatChoice(
8 | index = index, message = message.toAbstract(), finishReason = LlmMsg.FinishReason.fromValue(finishReason)
9 | )
10 | }
11 |
12 | private fun LlmMsg.FinishReason.Companion.fromValue(finishReason: String): LlmMsg.FinishReason {
13 | return enumValues().find { it.value == finishReason }
14 | ?: throw EnumConstantNotPresentException(LlmMsg.FinishReason::class.java, finishReason)
15 | }
16 |
17 | private fun com.theokanning.openai.completion.chat.ChatMessage.toAbstract(): LlmMsg.ChatMessage {
18 | return LlmMsg.ChatMessage(role = LlmMsg.ChatRole.fromValue(role), content = content, name = name)
19 | }
20 |
21 | private fun LlmMsg.ChatRole.Companion.fromValue(role: String): LlmMsg.ChatRole {
22 | return enumValues().find { it.value == role }
23 | ?: throw EnumConstantNotPresentException(LlmMsg.ChatRole::class.java, role)
24 | }
--------------------------------------------------------------------------------
/llm-modules/openai/src/main/kotlin/cc/unitmesh/openai/OpenAiEmbeddingProvider.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.openai
2 |
3 | import cc.unitmesh.nlp.embedding.Embedding
4 | import cc.unitmesh.nlp.embedding.EmbeddingProvider
5 | import com.theokanning.openai.embedding.EmbeddingRequest
6 | import com.theokanning.openai.service.OpenAiService
7 | import java.time.Duration
8 |
9 | class OpenAiEmbeddingProvider(var apiKey: String) : EmbeddingProvider {
10 | private val timeout = Duration.ofSeconds(600)
11 | var totalTokens = 0L
12 |
13 | private val openai: OpenAiService by lazy { OpenAiService(apiKey, timeout) }
14 |
15 | override fun embed(texts: List): List {
16 | val request = EmbeddingRequest.builder().model("text-embedding-ada-002").input(texts).build();
17 | val response = openai.createEmbeddings(request)
18 | totalTokens += response.usage.totalTokens
19 | return response.data.map { it.embedding }
20 | }
21 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/main/kotlin/cc/unitmesh/prompt/Main.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt
2 |
3 |
4 | fun main(args: Array) = PromptScriptCommand().main(args)
5 |
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/main/kotlin/cc/unitmesh/prompt/executor/strategy/RepeatExecuteStrategy.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.executor.strategy
2 |
3 | import cc.unitmesh.prompt.executor.base.SingleJobExecuteStrategy
4 | import cc.unitmesh.prompt.model.Job
5 | import cc.unitmesh.prompt.model.JobStrategy
6 | import com.google.gson.JsonObject
7 | import java.nio.file.Path
8 |
9 | class RepeatExecuteStrategy(
10 | override val jobName: String,
11 | override val job: Job,
12 | override val basePath: Path,
13 | private val strategy: JobStrategy.Repeat,
14 | ) : SingleJobExecuteStrategy(jobName, job, basePath) {
15 | override fun execute() {
16 | repeat(strategy.value) { index ->
17 | log.info("execute job: $jobName, strategy: repeat, times: ${index}/${strategy.value}")
18 | val llmResult = execSingleJob(jobName, job)
19 | handleJobResult(jobName, job, llmResult, JsonObject())
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/main/kotlin/cc/unitmesh/prompt/model/PromptScript.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.model
2 |
3 | import com.charleskorn.kaml.PolymorphismStyle
4 | import com.charleskorn.kaml.Yaml
5 | import com.charleskorn.kaml.YamlConfiguration
6 | import kotlinx.serialization.Serializable
7 |
8 | @Serializable
9 | data class PromptScript(
10 | val name: String,
11 | val description: String,
12 | val jobs: Map,
13 | ) {
14 | companion object {
15 | fun fromString(yamlString: String): PromptScript? {
16 | return try {
17 | val configuration = YamlConfiguration(polymorphismStyle = PolymorphismStyle.Property)
18 | Yaml(
19 | configuration = configuration,
20 | ).decodeFromString(serializer(), yamlString)
21 | } catch (e: Exception) {
22 | e.printStackTrace()
23 | null
24 | }
25 | }
26 | }
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/main/kotlin/cc/unitmesh/prompt/model/TemplateDatasource.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.model
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | /**
7 | * TemplateDatasource is the job's template datasource config, which will be used for render template.
8 | * The datasource can be a file, a directory or an http url, or a string, which be auto loaded by extension.
9 | * For example:
10 | *
11 | * ```yaml
12 | * template-datasource:
13 | * - type: file
14 | * value: datasource.json
15 | * ```
16 | *
17 | * We will load the datasource.json file as the template datasource.
18 | */
19 | @Serializable
20 | sealed class TemplateDatasource {
21 | /**
22 | * File is a file datasource, which will load data from a file.
23 | */
24 | @Serializable
25 | @SerialName("file")
26 | data class File(val value: String) : TemplateDatasource()
27 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/main/kotlin/cc/unitmesh/prompt/validate/JsonPathValidator.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.validate
2 |
3 | import com.jayway.jsonpath.JsonPath
4 |
5 | /**
6 | * JsonPath will validate is path is valid. If a path is invalid, will return false.
7 | */
8 | class JsonPathValidator(val expression: String, override val llmResult: String) : Validator {
9 | override fun validate(): Boolean = try {
10 | JsonPath.parse(llmResult).read(expression)
11 | true
12 | } catch (e: Exception) {
13 | false
14 | }
15 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/main/kotlin/cc/unitmesh/prompt/validate/JsonValidator.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.validate
2 |
3 | import com.google.gson.JsonParser
4 |
5 | /**
6 | * JsonValidator will validate is input is valid json. If input is invalid, will return false.
7 | */
8 | class JsonValidator(override val llmResult: String) : Validator {
9 | override fun validate(): Boolean {
10 | return try {
11 | JsonParser.parseString(llmResult)
12 | true
13 | } catch (e: Exception) {
14 | false
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/main/kotlin/cc/unitmesh/prompt/validate/MarkdownCodeBlockValidator.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.validate
2 |
3 | import cc.unitmesh.cf.core.parser.MarkdownCode
4 |
5 | class MarkdownCodeBlockValidator(override val llmResult: String) : Validator {
6 | override fun validate(): Boolean {
7 | val input = MarkdownCode.parse(llmResult)
8 | return input.text.isNotBlank()
9 | }
10 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/main/kotlin/cc/unitmesh/prompt/validate/RegexValidator.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.validate
2 |
3 | import java.util.regex.Pattern
4 |
5 | /**
6 | * RegexValidator will validate is input matches regex. If input is invalid, will return false.
7 | */
8 | class RegexValidator(val regex: String, override val llmResult: String) : Validator {
9 | override fun validate(): Boolean {
10 | val pattern = Pattern.compile(regex)
11 | val matcher = pattern.matcher(llmResult)
12 | return matcher.matches()
13 | }
14 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/main/kotlin/cc/unitmesh/prompt/validate/Validator.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.validate
2 |
3 | interface Validator {
4 | val llmResult: String
5 | fun validate(): Boolean
6 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UTF-8
6 |
7 | [CF] %logger{20} %msg%n
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/kotlin/cc/unitmesh/prompt/PromptManagerTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt;
2 |
3 | import cc.unitmesh.prompt.template.TemplateDataCompile
4 | import io.kotest.matchers.string.shouldContain
5 | import org.junit.jupiter.api.Test
6 |
7 | class TemplateDataCompileTests {
8 | private val manager = TemplateDataCompile()
9 |
10 | @Test
11 | fun should_return_prompt_when_getPrompt_called() {
12 | val data = javaClass.getResource("/testdata/sample.json")!!.toURI()
13 | val template = javaClass.getResource("/testdata/ui-clarify.open_ai.vm")!!.toURI()
14 |
15 | val output = manager.compile(template.path, data.path)
16 | output shouldContain "中国的首都是哪里"
17 | // TODO: spike why not working in Windows, since I don't have Windows development env.
18 | // output shouldBe """system:
19 | // |You are a helpful assistant.
20 | // |
21 | // |user:
22 | // |中国的首都是哪里?
23 | // |assistant:
24 | // |北京
25 | // |
26 | // |user:
27 | // |中国的首都是哪里?
28 | // |""".trimMargin()
29 | }
30 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/kotlin/cc/unitmesh/prompt/PromptScriptCommandTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt;
2 |
3 | import com.github.ajalt.clikt.testing.test
4 | import io.kotest.matchers.shouldBe
5 | import org.junit.jupiter.api.Test
6 | import java.io.File
7 | import kotlin.test.Ignore
8 |
9 | class PromptScriptCommandTest {
10 | @Test
11 | @Ignore
12 | fun should_print_test() {
13 | // given
14 | val command = PromptScriptCommand()
15 | val inputFile = File(".").resolve("../../examples/prompt-script/prompt.unit-mesh.yml").absolutePath.toString()
16 | val result = command.test("--input $inputFile")
17 |
18 |
19 | result.statusCode shouldBe 0
20 | // when
21 | // command.run()
22 | }
23 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/kotlin/cc/unitmesh/prompt/model/ValidateRuleTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.model
2 |
3 | import com.charleskorn.kaml.PolymorphismStyle
4 | import com.charleskorn.kaml.Yaml
5 | import com.charleskorn.kaml.YamlConfiguration
6 | import io.kotest.matchers.shouldBe
7 | import org.junit.jupiter.api.Test
8 |
9 | class ValidateRuleTest {
10 | @Test
11 | fun should_serialize_from_ext_tool_with_options_yaml() {
12 | val yaml = """
13 | type: ext-tool
14 | value: dot -Tsvg basic.dot -o basic.svg
15 | options:
16 | key: test
17 | value: test
18 | """.trimIndent()
19 |
20 | val configuration = YamlConfiguration(polymorphismStyle = PolymorphismStyle.Property)
21 | val validateRule = Yaml(configuration = configuration).decodeFromString(ValidateRule.serializer(), yaml)
22 |
23 | (validateRule is ValidateRule.ExtTool) shouldBe true
24 | val extTool = validateRule as ValidateRule.ExtTool
25 | extTool.value shouldBe "dot -Tsvg basic.dot -o basic.svg"
26 | extTool.options["key"] shouldBe "test"
27 | }
28 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/kotlin/cc/unitmesh/prompt/model/VariableTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.model;
2 |
3 | import org.junit.jupiter.api.Assertions.assertEquals
4 | import org.junit.jupiter.api.Test
5 | import java.math.BigDecimal
6 |
7 | class VariableTest {
8 |
9 | @Test
10 | fun should_return_range_with_integer_step() {
11 | val range = Variable.Range("key", "0~100", "1")
12 | val result: ClosedRange = range.toRange()
13 | assertEquals(0.toBigDecimal().rangeTo(100.toBigDecimal()), result)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/kotlin/cc/unitmesh/prompt/validate/ExtToolValidatorTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.validate;
2 |
3 | import org.junit.jupiter.api.Assertions.assertEquals
4 | import org.junit.jupiter.api.Test
5 |
6 | class ExtToolValidatorTest {
7 | @Test
8 | fun should_return_true_when_command_executes_successfully() {
9 | // given
10 | val execCommand = "ls -l"
11 | val input = ""
12 | val options = mapOf()
13 |
14 | // when
15 | val result = ExtToolValidator(execCommand, input, options).validate()
16 |
17 | // then
18 | assertEquals(true, result)
19 | }
20 |
21 | @Test
22 | fun should_return_true_when_command_executes_successfully_with_input() {
23 | // given
24 | val execCommand = "ls -l"
25 | val input = "src"
26 | val options = mapOf()
27 |
28 | // when
29 | val result = ExtToolValidator(execCommand, input, options).validate()
30 |
31 | // then
32 | assertEquals(true, result)
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/kotlin/cc/unitmesh/prompt/validate/JsonPathValidatorTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.validate;
2 |
3 | import cc.unitmesh.docs.SampleCode
4 | import io.kotest.matchers.shouldBe
5 | import org.junit.jupiter.api.Test
6 |
7 | class JsonPathValidatorTest {
8 | @Test
9 | @SampleCode(name = "检验成功", content = "")
10 | fun should_return_true_when_path_is_valid() {
11 | // start-sample
12 | val expression = "$.name"
13 | val input = "{\"name\": \"John\", \"age\": 30}"
14 | // end-sample
15 |
16 | // when
17 | val validator = JsonPathValidator(expression, input)
18 | val result = validator.validate()
19 |
20 | // then
21 | result shouldBe true
22 | }
23 |
24 | @Test
25 | @SampleCode(name = "校验失败", content = "")
26 | fun should_return_false_when_path_is_invalid() {
27 | // start-sample
28 | val expression = "$.address"
29 | val input = "{\"name\": \"John\", \"age\": 30}"
30 | // end-sample
31 |
32 | // when
33 | val validator = JsonPathValidator(expression, input)
34 | val result = validator.validate()
35 |
36 | // then
37 | result shouldBe false
38 | }
39 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/kotlin/cc/unitmesh/prompt/validate/JsonValidatorTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.validate;
2 |
3 | class JsonValidatorTest {
4 |
5 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/kotlin/cc/unitmesh/prompt/validate/MarkdownCodeBlockValidatorTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.validate;
2 |
3 | import cc.unitmesh.docs.SampleCode
4 | import org.junit.jupiter.api.Assertions.*
5 | import org.junit.jupiter.api.Test
6 |
7 | class MarkdownCodeBlockValidatorTest {
8 |
9 | @Test
10 | @SampleCode(name = "成功场景", content = "当代码块不为空里,返回 true。")
11 | fun should_return_true_when_input_has_non_blank_text() {
12 | // start-sample
13 | val input = "```kotlin\nval x = 10\n```"
14 | // end-sample
15 |
16 | val validator = MarkdownCodeBlockValidator(input)
17 |
18 | // when
19 | val result = validator.validate()
20 |
21 | // then
22 | assertTrue(result)
23 | }
24 |
25 | @Test
26 | @SampleCode(name = "成功场景", content = "当代码块为空时,返回 false。")
27 | fun should_return_false_when_input_has_blank_text() {
28 | // start-sample
29 | val input = "```kotlin\n\n```"
30 | // end-sample
31 |
32 | val validator = MarkdownCodeBlockValidator(input)
33 |
34 | // when
35 | val result = validator.validate()
36 |
37 | // then
38 | assertFalse(result)
39 | }
40 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/kotlin/cc/unitmesh/prompt/validate/RegexValidatorTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.validate;
2 |
3 | import org.junit.jupiter.api.Assertions.*
4 | import org.junit.jupiter.api.Test
5 |
6 | class RegexValidatorTest {
7 |
8 | @Test
9 | fun shouldReturnTrueForValidInput() {
10 | // Given
11 | val regex = "\\d{4}" // Example regex pattern for 4 digits
12 | val input = "1234"
13 | val validator = RegexValidator(regex, input)
14 |
15 | // When
16 | val result = validator.validate()
17 |
18 | // Then
19 | assertTrue(result)
20 | }
21 |
22 | @Test
23 | fun shouldReturnFalseForInvalidInput() {
24 | // Given
25 | val regex = "\\d{4}" // Example regex pattern for 4 digits
26 | val input = "abc"
27 | val validator = RegexValidator(regex, input)
28 |
29 | // When
30 | val result = validator.validate()
31 |
32 | // Then
33 | assertFalse(result)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/kotlin/cc/unitmesh/prompt/validate/StringValidatorTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.prompt.validate;
2 |
3 | import cc.unitmesh.docs.SampleCode
4 | import io.kotest.matchers.shouldBe
5 | import org.junit.jupiter.api.Test
6 |
7 | class StringValidatorTest {
8 |
9 | @Test
10 | @SampleCode(name = "成功场景", content = "")
11 | fun string_eval() {
12 | // start-sample
13 | val expr1 = "output contains \"hello\""
14 | val expr2 = "output endsWith \"world\""
15 | val expr3 = "output startsWith \"hello\""
16 | val expr4 = "output == \"hello world\""
17 | val expr5 = "output == 'hello world'"
18 | val expr6 = "output.length > 5"
19 | // end-sample
20 |
21 | StringValidator(expr1, "hello world").validate() shouldBe true
22 | StringValidator(expr2, "hello world").validate() shouldBe true
23 | StringValidator(expr3, "hello world").validate() shouldBe true
24 | StringValidator(expr4, "hello world").validate() shouldBe true
25 | StringValidator(expr5, "hello world").validate() shouldBe true
26 | StringValidator(expr6, "hello, world").validate() shouldBe true
27 | }
28 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/resources/connection/prompt-connection.yml:
--------------------------------------------------------------------------------
1 | $schema: schemas/OpenAIConnection.schema.json
2 | name: open_ai_connection
3 | type: MockLlm
4 | configs:
5 | api-host: "http://mock.unitmesh.cc"
6 | organization: "" # optional
7 | secrets:
8 | api-key: "some keys"
9 | api-type: "azure"
10 |
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/resources/flow/flow.dag.yaml:
--------------------------------------------------------------------------------
1 | $schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
2 | inputs:
3 | chat_history:
4 | type: list
5 | default: []
6 | question:
7 | type: string
8 | is_chat_input: true
9 | default: What is ChatGPT?
10 | outputs:
11 | answer:
12 | type: string
13 | reference: ${chat.output}
14 | is_chat_output: true
15 | nodes:
16 | - inputs:
17 | # This is to easily switch between openai and azure openai.
18 | # deployment_name is required by azure openai, model is required by openai.
19 | deployment_name: gpt-35-turbo
20 | model: gpt-3.5-turbo
21 | max_tokens: "256"
22 | temperature: "0.7"
23 | chat_history: ${inputs.chat_history}
24 | question: ${inputs.question}
25 | name: chat
26 | type: llm
27 | source:
28 | type: code
29 | path: chat.jinja2
30 | api: chat
31 | connection: open_ai_connection
32 | node_variants: {}
33 | environment:
34 | python_requirements_txt: requirements.txt
35 |
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/resources/prompt.unit-mesh.yml:
--------------------------------------------------------------------------------
1 | name: "Open AI Verifier"
2 | description: "Verify Open AI's LLM"
3 |
4 | jobs:
5 | prompt-evaluate: # job name should be unique for each job
6 | description: "Evaluate prompt with different parameters"
7 | connection: connections.yml
8 | template: code-complete.open-ai.vm # auto choice template by extension
9 | template-datasource:
10 | - type: file
11 | value: testdata/sample.json
12 |
13 | strategy:
14 | - type: connection
15 | value:
16 | - type: range
17 | key: temperature
18 | range: 0.0~1.0
19 | step: 0.1
20 | - type: repeat
21 | value: 1000
22 |
23 | validate: # optional
24 | - type: json-path
25 | value: $.output.id
26 | - type: string
27 | value: output.length < 300
28 |
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/resources/testdata/sample.json:
--------------------------------------------------------------------------------
1 | {
2 | "question": "中国的首都是哪里?",
3 | "chat_history": [
4 | {
5 | "inputs": {
6 | "role": "user",
7 | "question": "中国的首都是哪里?"
8 | },
9 | "outputs": {
10 | "role": "assistant",
11 | "answer": "北京"
12 | }
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/llm-modules/prompt-script/src/test/resources/testdata/ui-clarify.open_ai.vm:
--------------------------------------------------------------------------------
1 | system:
2 | You are a helpful assistant.
3 |
4 | #foreach ($item in $chat_history)
5 | user:
6 | ${item.inputs.question}
7 | assistant:
8 | ${item.outputs.answer}
9 | #end
10 |
11 | user:
12 | ${question}
13 |
--------------------------------------------------------------------------------
/llm-tools/interpreter/.gitignore:
--------------------------------------------------------------------------------
1 | lets-plot-images/*
--------------------------------------------------------------------------------
/llm-tools/interpreter/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(libs.plugins.jvm)
3 | alias(libs.plugins.serialization)
4 | alias(libs.plugins.jupyter)
5 | }
6 |
7 | dependencies {
8 | implementation(libs.kotlin.reflect)
9 | implementation(libs.coroutines.core)
10 |
11 | implementation(libs.jupyter.api)
12 | implementation(libs.jupyter.kernel)
13 |
14 | implementation(libs.bundles.letsPlot)
15 |
16 | // tips: don't add follow deps to project will cause issues
17 | compileOnly("org.jetbrains.kotlin:kotlin-scripting-jvm")
18 |
19 | testImplementation(libs.bundles.test)
20 | }
21 |
--------------------------------------------------------------------------------
/llm-tools/interpreter/src/main/kotlin/cc/unitmesh/code/interpreter/api/InterpreterRequest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.code.interpreter.api
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class InterpreterRequest(
7 | var id: Int = -1,
8 | var code: String,
9 | val language: String = "kotlin",
10 | val history: Boolean = false,
11 | var port: Int = 8080
12 | )
13 |
--------------------------------------------------------------------------------
/llm-tools/interpreter/src/main/kotlin/cc/unitmesh/code/magic/SimpleMagicMatcher.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.code.magic
2 |
3 | class SimpleMagicMatcher {
4 | private val USE_REGEX = Regex("""^\s*%use\s+([\w, ]+)""")
5 |
6 | /**
7 | * Parse magics from code
8 | * @param code code to parse
9 | * @return list of langs, like [spring, ktor, mysql]
10 | *
11 | * examples:
12 | * code = "%use spring" -> return ["spring"]
13 | * code = "%use spring, mysql" -> return ["spring", "mysql"]
14 | * code = """%use mysql
15 | * %use spring
16 | * """ -> return ["mysql", "spring"]
17 | */
18 | fun parseLang(code: String): List {
19 | val magics = mutableListOf()
20 | val pattern = USE_REGEX
21 | for (line in code.lines()) {
22 | val matchResult = pattern.matchEntire(line.trim())
23 | if (matchResult != null) {
24 | val langs = matchResult.groupValues[1].split(",").map { it.trim() }
25 | magics.addAll(langs)
26 | }
27 | }
28 | return magics
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/llm-tools/interpreter/src/main/kotlin/cc/unitmesh/code/magic/lang/KtorLangBuilder.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.code.magic.lang
2 |
3 | class KtorLangBuilder(private val code: String, private val port: Int): LangBuilder {
4 | override fun build(): String {
5 | return """$code
6 |
7 | fun main() {
8 | val classToStart = Server::class.java.name
9 |
10 | val ktClass = ::main::class.java.classLoader.loadClass(classToStart).kotlin
11 | val instance = (ktClass.primaryConstructor?.call() ?: ktClass.objectInstance) as? KotlessAWS
12 |
13 | val kotless = instance ?: error("instance inherit from Kotless!")
14 |
15 | embeddedServer(Netty, ${port}) {
16 | kotless.prepare(this)
17 | }.start(wait = true)
18 | }
19 |
20 | main()
21 | """
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/llm-tools/interpreter/src/main/kotlin/cc/unitmesh/code/magic/lang/LangBuilder.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.code.magic.lang
2 |
3 | interface LangBuilder {
4 | fun build(): String
5 | }
--------------------------------------------------------------------------------
/llm-tools/interpreter/src/main/kotlin/cc/unitmesh/code/messaging/Message.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.code.messaging
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class Message(
7 | var id: Int = -1,
8 | var resultValue: String,
9 | var displayValue: String,
10 | var className: String = "",
11 | var msgType: MessageType = MessageType.NONE,
12 | var content: MessageContent? = null,
13 | )
14 |
--------------------------------------------------------------------------------
/llm-tools/interpreter/src/test/kotlin/cc/unitmesh/code/interpreter/KotlinReplWrapperTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.code.interpreter
2 |
3 | import cc.unitmesh.code.interpreter.compiler.KotlinReplWrapper
4 | import io.kotest.matchers.shouldBe
5 | import org.junit.jupiter.api.BeforeEach
6 | import org.junit.jupiter.api.Test
7 |
8 | class KotlinReplWrapperTest {
9 | private lateinit var compiler: KotlinReplWrapper
10 |
11 | @BeforeEach
12 | internal fun setUp() {
13 | this.compiler = KotlinReplWrapper()
14 | }
15 |
16 | @Test
17 | internal fun simple_eval() {
18 | compiler.eval("val x = 3")
19 | val res = compiler.eval("x*2")
20 | res.rawValue shouldBe 6
21 | }
22 |
23 | @Test
24 | internal fun multiple_table() {
25 | compiler.eval("""fun generateMultiplicationTable(): String {
26 | val sb = StringBuilder()
27 | for (i in 1..9) {
28 | for (j in 1..9) {
29 | sb.append("'${'$'}{i * j}\t")
30 | }
31 | sb.append("\n")
32 | }
33 | return sb.toString()
34 | }
35 |
36 | val multiplicationTable = generateMultiplicationTable()
37 | multiplicationTable""")
38 | }
39 | }
--------------------------------------------------------------------------------
/llm-tools/web-tools/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | java
4 | alias(libs.plugins.jvm)
5 | alias(libs.plugins.serialization)
6 | }
7 |
8 | dependencies {
9 | implementation(projects.cocoaCore)
10 | implementation(libs.kotlin.stdlib)
11 | implementation(libs.serialization.json)
12 |
13 | implementation(libs.jsoup)
14 |
15 | testImplementation(libs.bundles.test)
16 | testRuntimeOnly(libs.test.junit.engine)
17 | }
18 |
--------------------------------------------------------------------------------
/llm-tools/web-tools/src/test/kotlin/cc/unitmesh/tools/web/WikimediaTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.tools.web;
2 |
3 | import org.junit.jupiter.api.Test
4 | import kotlin.test.Ignore
5 |
6 | class MyServiceTest {
7 |
8 |
9 | @Test
10 | @Ignore
11 | fun should_return_url_list_when_run_with_valid_title() {
12 | Wikimedia().run("Intellij").forEach { println(it) }
13 | }
14 | }
--------------------------------------------------------------------------------
/nginx/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM nginx:alpine
2 |
3 | # Remove any existing config files
4 | RUN rm /etc/nginx/conf.d/*
5 |
6 | # Copy config files
7 | # *.conf files in "conf.d/" dir get included in main config
8 | COPY ./default.conf /etc/nginx/conf.d/
9 |
10 | # Expose the listening port
11 | EXPOSE 80
12 |
13 | # Launch NGINX
14 | CMD [ "nginx", "-g", "daemon off;" ]
15 |
--------------------------------------------------------------------------------
/packages/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 | .pnp
6 | .pnp.js
7 |
8 | # testing
9 | coverage
10 |
11 | # next.js
12 | .next/
13 | out/
14 | build
15 |
16 | # misc
17 | .DS_Store
18 | *.pem
19 |
20 | # debug
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 | .pnpm-debug.log*
25 |
26 | # local env files
27 | .env.local
28 | .env.development.local
29 | .env.test.local
30 | .env.production.local
31 |
32 | # turbo
33 | .turbo
34 |
35 | .contentlayer
36 | .env
37 | .vercel
38 | .vscode
--------------------------------------------------------------------------------
/packages/ui-components-parser/.gitignore:
--------------------------------------------------------------------------------
1 | mui/*.json
--------------------------------------------------------------------------------
/packages/ui-components-parser/README.md:
--------------------------------------------------------------------------------
1 | # UI Components Parser
2 |
3 | > 用于解析项目中的 UI 组件库。
4 |
5 | ## MUI 示例
6 |
7 | 需要解析的部分:
8 |
9 | - 组件名称
10 | - 组件描述
11 | - 组件属性
12 | - 组件示例
13 |
14 | 步骤:
15 |
16 | 1. `git clone https://github.com/mui/material-ui --depth=1`
17 | 2. walkdir in docs
18 | 3. filter `.ts.preview` & `.zh.md` files
--------------------------------------------------------------------------------
/packages/ui-components-parser/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ui-components-parser",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "MPL-2.0",
12 | "dependencies": {
13 | "acorn": "^8.10.0",
14 | "acorn-jsx": "^5.3.2",
15 | "gray-matter": "^4.0.3",
16 | "jsdom": "^22.1.0",
17 | "marked": "^9.0.0",
18 | "typescript": "^5.2.2"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/rag-modules/document/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | java
4 | alias(libs.plugins.jvm)
5 | alias(libs.plugins.serialization)
6 | }
7 |
8 | dependencies {
9 | implementation(projects.cocoaCore)
10 | implementation(libs.kotlin.stdlib)
11 | implementation(libs.serialization.json)
12 |
13 | implementation("org.apache.pdfbox:pdfbox:3.0.0")
14 | implementation("org.apache.poi:poi:5.2.3")
15 | implementation("org.apache.poi:poi-ooxml:5.2.3")
16 | implementation("org.apache.poi:poi-scratchpad:5.2.3")
17 |
18 | testImplementation(libs.bundles.test)
19 | testRuntimeOnly(libs.test.junit.engine)
20 | }
21 |
--------------------------------------------------------------------------------
/rag-modules/document/src/main/kotlin/cc/unitmesh/document/parser/MdDocumentParser.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.document.parser
2 |
3 | import cc.unitmesh.rag.document.Document
4 | import cc.unitmesh.rag.document.DocumentParser
5 | import cc.unitmesh.rag.splitter.MarkdownHeaderTextSplitter
6 | import java.io.InputStream
7 |
8 | /**
9 | * Markdown Document Parser
10 | *
11 | * This class represents a parser for Markdown documents.
12 | *
13 | * The MdDocumentParser class uses the [MarkdownHeaderTextSplitter] class to split the text of the document
14 | * into separate sections based on the headers in the Markdown syntax. It then returns a list of Document
15 | * objects representing each section of the document.
16 | *
17 | * Example usage:
18 | * ```
19 | * val parser = MdDocumentParser()
20 | * val inputStream = FileInputStream("document.md")
21 | * val documents = parser.parse(inputStream)
22 | * ```
23 | *
24 | * @constructor Creates an instance of MdDocumentParser.
25 | */
26 | class MdDocumentParser : DocumentParser {
27 | private val splitter = MarkdownHeaderTextSplitter(listOf())
28 | override fun parse(inputStream: InputStream): List {
29 | return splitter.splitText(inputStream.bufferedReader().readText())
30 | }
31 | }
--------------------------------------------------------------------------------
/rag-modules/document/src/test/kotlin/cc/unitmesh/document/parser/MdDocumentParserTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.document.parser;
2 |
3 | import cc.unitmesh.docs.SampleCode
4 | import io.kotest.matchers.shouldBe
5 | import org.junit.jupiter.api.Test
6 | import java.io.ByteArrayInputStream
7 |
8 | class MdDocumentParserTest {
9 | @Test
10 | @SampleCode
11 | fun should_parse_input_stream_to_list_of_documents() {
12 | // start-sample
13 | val parser = MdDocumentParser()
14 | val inputStream = ByteArrayInputStream("Sample Markdown Text".toByteArray())
15 | val result = parser.parse(inputStream)
16 | // end-sample
17 |
18 | // then
19 | result.size shouldBe 1
20 | }
21 | }
--------------------------------------------------------------------------------
/rag-modules/document/src/test/kotlin/cc/unitmesh/document/parser/MsOfficeDocumentParserTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.document.parser;
2 |
3 | import cc.unitmesh.rag.document.DocumentType
4 | import org.junit.jupiter.api.Test
5 |
6 | class MsOfficeDocumentParserTest {
7 | @Test
8 | fun should_parse_pptx_file() {
9 | val inputStream = this.javaClass.getResourceAsStream("/sample.pptx")!!
10 | val documents = MsOfficeDocumentParser(DocumentType.PPT).parse(inputStream)
11 |
12 | assert(documents[0].text.contains("代码库问答"))
13 | assert(documents[1].text.contains("智能数据问答场景"))
14 | }
15 |
16 | @Test
17 | fun should_convert_word_to_markdown_text() {
18 | val inputStream = this.javaClass.getResourceAsStream("/ChocolateFactory.docx")!!
19 | val documents = MsOfficeDocumentParser(DocumentType.DOC).parse(inputStream)
20 |
21 | assert(documents[0].text.contains("Chocolate Factory"))
22 | }
23 | }
--------------------------------------------------------------------------------
/rag-modules/document/src/test/resources/ChocolateFactory.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unit-mesh/choco-builder/fdd4d700f9dc04d0bdef3bbc41b8955804cad135/rag-modules/document/src/test/resources/ChocolateFactory.docx
--------------------------------------------------------------------------------
/rag-modules/document/src/test/resources/sample.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unit-mesh/choco-builder/fdd4d700f9dc04d0bdef3bbc41b8955804cad135/rag-modules/document/src/test/resources/sample.pptx
--------------------------------------------------------------------------------
/rag-modules/rag-script/.gitignore:
--------------------------------------------------------------------------------
1 | temp
2 | dependencies/
3 | 0_codes.json
4 | .env
--------------------------------------------------------------------------------
/rag-modules/rag-script/README.md:
--------------------------------------------------------------------------------
1 | # RAGScript
2 |
3 | RAGScript 是一个使用 Kotlin DSL 的脚本语言,以用于快速使用、构建 RAG (检索增强,Retrieval Augmented Generation)应用的 PoC。
4 |
5 | ## Usage
6 |
7 | ```
8 | // 声明依赖
9 | @file:DependsOn("cc.unitmesh:rag-script:0.3.3")
10 |
11 | // 引入 RAGScript 依赖
12 | import cc.unitmesh.rag.*
13 |
14 | rag {
15 | // 使用 OpenAI 作为 LLM 引擎
16 | llm = LlmConnector(LlmType.OpenAI)
17 | // 使用 SentenceTransformers 作为 Embedding 引擎
18 | embedding = EmbeddingEngine(EngineType.SentenceTransformers)
19 | // 使用 Memory 作为 Retriever
20 | store = Store(StoreType.Memory)
21 |
22 | indexing {
23 | // 从文件中读取文档
24 | val document = document("filename.txt")
25 | // 将文档切割成 chunk
26 | val chunks = document.split()
27 | // 建立索引
28 | store.indexing(chunks)
29 | }
30 |
31 | querying {
32 | // 查询
33 | store.findRelevant("workflow dsl design ").also {
34 | println(it)
35 | }
36 | }
37 | }
38 | ```
39 |
40 |
--------------------------------------------------------------------------------
/rag-modules/rag-script/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | java
4 | alias(libs.plugins.jvm)
5 | alias(libs.plugins.serialization)
6 |
7 | id("com.google.devtools.ksp") version "1.9.10-1.0.13"
8 | }
9 |
10 | dependencies {
11 | implementation(projects.cocoaCore)
12 | implementation(projects.ragModules.document)
13 | implementation(projects.ragModules.storeElasticsearch)
14 | implementation(projects.codeModules.codeSplitter)
15 | implementation(projects.llmModules.localEmbedding)
16 | implementation(projects.llmModules.openai)
17 |
18 | implementation(libs.chapi.domain)
19 |
20 | implementation(libs.kotlin.stdlib)
21 | implementation(libs.serialization.json)
22 |
23 | implementation(libs.huggingface.tokenizers)
24 |
25 | implementation(libs.dotenv.kotlin)
26 |
27 | implementation(libs.ktor.client.logging)
28 | implementation(libs.ktor.client.core)
29 | implementation(libs.ktor.client.cio)
30 |
31 | implementation(libs.rxjava3)
32 |
33 | testImplementation(libs.bundles.test)
34 | testRuntimeOnly(libs.test.junit.engine)
35 | }
36 |
--------------------------------------------------------------------------------
/rag-modules/rag-script/docs/metric.md:
--------------------------------------------------------------------------------
1 | # Metric
2 |
3 | [A Metrics-First Approach to LLM Evaluation](https://www.rungalileo.io/blog/metrics-first-approach-to-llm-evaluation)
4 |
5 | 
6 |
7 | ```yaml
8 | name: chat_with_pdf_default_20230820_162219_559000
9 | flow: .
10 | data: ./data/bert-paper-qna.jsonl
11 | #run:
12 | column_mapping:
13 | chat_history: ${data.chat_history}
14 | pdf_url: ${data.pdf_url}
15 | question: ${data.question}
16 | config:
17 | EMBEDDING_MODEL_DEPLOYMENT_NAME: text-embedding-ada-002
18 | CHAT_MODEL_DEPLOYMENT_NAME: gpt-35-turbo
19 | PROMPT_TOKEN_LIMIT: 3000
20 | MAX_COMPLETION_TOKENS: 1024
21 | VERBOSE: true
22 | CHUNK_SIZE: 256
23 | CHUNK_OVERLAP: 64
24 | ```
25 |
26 |
--------------------------------------------------------------------------------
/rag-modules/rag-script/src/main/kotlin/cc/unitmesh/rag/CodeDsl.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag
2 |
3 | import cc.unitmesh.cf.code.CodeSplitter
4 |
5 | /**
6 | *
7 | */
8 | class CodeDsl(file: String) {
9 | val codeSplitter = CodeSplitter(file)
10 |
11 | fun split(): List {
12 | return listOf()
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/rag-modules/rag-script/src/main/kotlin/cc/unitmesh/rag/EmbeddingEngine.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag
2 |
3 | import cc.unitmesh.cf.LocalEmbedding
4 | import cc.unitmesh.nlp.embedding.Embedding
5 | import cc.unitmesh.nlp.embedding.EmbeddingProvider
6 | import cc.unitmesh.nlp.embedding.text.EnglishTextEmbeddingProvider
7 |
8 | enum class EngineType {
9 | EnglishTextEmbedding,
10 | SentenceTransformers,
11 | TextEmbeddingAda,
12 | }
13 |
14 | class EmbeddingEngine(private val engine: EngineType = EngineType.SentenceTransformers) {
15 | var provider: EmbeddingProvider = when (engine) {
16 | EngineType.SentenceTransformers -> LocalTransformersEmbedding()
17 | EngineType.EnglishTextEmbedding -> EnglishTextEmbeddingProvider()
18 | EngineType.TextEmbeddingAda -> TODO()
19 | }
20 | }
21 |
22 | class LocalTransformersEmbedding : EmbeddingProvider {
23 | private val semantic = LocalEmbedding.create()
24 | override fun embed(texts: List): List {
25 | return texts.map {
26 | semantic.embed(it).toList()
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/rag-modules/rag-script/src/main/kotlin/cc/unitmesh/rag/HttpDsl.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag
2 |
3 |
4 | import io.ktor.client.*
5 | import io.ktor.client.call.*
6 | import io.ktor.client.request.*
7 | import io.ktor.client.statement.*
8 | import kotlinx.coroutines.runBlocking
9 | import java.io.File
10 |
11 | object Http {
12 | private val client = HttpClient()
13 |
14 | /**
15 | * @param url
16 | */
17 | fun get(url: String = "", init: () -> Unit) {
18 | runBlocking {
19 | client.get(url) {
20 | init()
21 | }
22 | }
23 | }
24 |
25 | fun download(url: String): File {
26 | val fileName = url.substringAfterLast("/")
27 | val file = File("temp", fileName)
28 |
29 | if (!File("temp").exists()) {
30 | File("temp").mkdir()
31 | }
32 |
33 | if (file.exists()) {
34 | return file
35 | }
36 |
37 | runBlocking {
38 | val httpResponse: HttpResponse = client.get(url) {}
39 | val responseBody: ByteArray = httpResponse.body()
40 | file.writeBytes(responseBody)
41 | }
42 |
43 | return file
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/rag-modules/rag-script/src/main/kotlin/cc/unitmesh/rag/Text.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag
2 |
3 | import cc.unitmesh.document.parser.TextDocumentParser
4 | import cc.unitmesh.rag.document.Document
5 | import cc.unitmesh.rag.document.DocumentParser
6 | import cc.unitmesh.rag.document.DocumentType
7 |
8 | class Text(private val text: String) {
9 | private val documentParser: DocumentParser = TextDocumentParser(DocumentType.TXT)
10 |
11 | fun split(): List {
12 | return documentParser.parse(text.byteInputStream())
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/rag-modules/rag-script/src/main/kotlin/cc/unitmesh/rag/base/RagScript.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag.base
2 |
3 | @DslMarker
4 | annotation class RagScript
--------------------------------------------------------------------------------
/rag-modules/rag-script/src/test/kotlin/cc/unitmesh/rag/PromptTextTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.rag;
2 |
3 | import cc.unitmesh.docs.SampleCode
4 | import io.kotest.matchers.shouldBe
5 | import org.junit.jupiter.api.Test
6 |
7 | class PromptTextTest {
8 | @Test
9 | @SampleCode(name = "PromptScript", content = "")
10 | fun template_example() {
11 | val promptText =
12 | // start-sample
13 | prompt {
14 | paragraph("Hello World")
15 | codeblock("kotlin") {
16 | "println(\"Hello World\")"
17 | }
18 | list(ListType.Unordered) {
19 | listOf("Hello", "World")
20 | }
21 | }
22 | // end-sample
23 |
24 | promptText.toString() shouldBe """Hello World
25 | |```kotlin
26 | |println("Hello World")
27 | |```
28 | |* Hello
29 | |* World
30 | |""".trimMargin()
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/rag-modules/store-elasticsearch/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | java
4 | alias(libs.plugins.jvm)
5 | alias(libs.plugins.serialization)
6 | }
7 |
8 | dependencies {
9 | implementation(projects.cocoaCore)
10 | implementation(libs.kotlin.stdlib)
11 | implementation(libs.serialization.json)
12 |
13 | implementation("co.elastic.clients:elasticsearch-java:8.10.0")
14 | implementation(libs.jackson.databind)
15 | implementation(libs.slf4j.api)
16 |
17 | testImplementation(libs.bundles.test)
18 | testRuntimeOnly(libs.test.junit.engine)
19 | }
20 |
--------------------------------------------------------------------------------
/rag-modules/store-elasticsearch/src/main/kotlin/cc/unitmesh/store/ElasticsearchRequestFailedException.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.store
2 |
3 | internal class ElasticsearchRequestFailedException : RuntimeException {
4 | constructor() : super()
5 | constructor(message: String) : super(message)
6 | constructor(message: String, cause: Throwable) : super(message, cause)
7 | }
8 |
--------------------------------------------------------------------------------
/rag-modules/store-milvus/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | java
4 | alias(libs.plugins.jvm)
5 | alias(libs.plugins.serialization)
6 | }
7 |
8 | dependencies {
9 | implementation(projects.cocoaCore)
10 | implementation(libs.kotlin.stdlib)
11 | implementation(libs.serialization.json)
12 |
13 | implementation("io.milvus:milvus-sdk-java:2.3.0")
14 |
15 | testImplementation(libs.bundles.test)
16 | testRuntimeOnly(libs.test.junit.engine)
17 | }
18 |
--------------------------------------------------------------------------------
/rag-modules/store-pinecone/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @Suppress("DSL_SCOPE_VIOLATION")
2 | plugins {
3 | java
4 | alias(libs.plugins.jvm)
5 | alias(libs.plugins.serialization)
6 | }
7 |
8 | dependencies {
9 | implementation(projects.cocoaCore)
10 | implementation(libs.kotlin.stdlib)
11 | implementation(libs.serialization.json)
12 |
13 | implementation("io.pinecone:pinecone-client:0.4.0")
14 |
15 | testImplementation(libs.bundles.test)
16 | testRuntimeOnly(libs.test.junit.engine)
17 | }
18 |
--------------------------------------------------------------------------------
/server/elastic-search.http:
--------------------------------------------------------------------------------
1 | ### Localhost
2 | GET http://localhost:18080/api/code?q="archguard"
3 |
4 | ### ElasticSearch
5 | DELETE http://localhost:9200/chocolate-code
6 | Content-Type: application/json
7 |
8 | # curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
9 | #{
10 | # "query": {
11 | # "query_string": {
12 | # "query": "(new york city) OR (big apple)",
13 | # "default_field": "content"
14 | # }
15 | # }
16 | #}
17 | ### ElasticSearch
18 | GET localhost:9200/chocolate-code/_search?pretty
19 | Content-Type: application/json
20 |
21 | {
22 | "query": { "match_all": {} },
23 | "_source": ["id", "text"]
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/ChocolateFactoryApplication.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf
2 |
3 | import org.springframework.boot.autoconfigure.SpringBootApplication
4 | import org.springframework.boot.context.properties.ConfigurationPropertiesScan
5 | import org.springframework.boot.runApplication
6 |
7 | @SpringBootApplication
8 | @ConfigurationPropertiesScan
9 | class ChocolateFactoryApplication
10 |
11 | fun main(args: Array) {
12 | runApplication(*args)
13 | }
14 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/DomainClassify.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains
2 |
3 | import cc.unitmesh.cf.core.flow.DomainDeclaration
4 | import org.reflections.Reflections
5 | import org.reflections.util.ConfigurationBuilder
6 | import org.springframework.stereotype.Component
7 |
8 |
9 | @Component
10 | class DomainClassify {
11 | val cachedDomains: MutableMap = mutableMapOf()
12 |
13 | private val packageName = DomainClassify::class.java.`package`.name
14 |
15 | fun lookupDomains(): MutableMap {
16 | if (cachedDomains.isNotEmpty()) {
17 | return cachedDomains
18 | }
19 |
20 | Reflections(ConfigurationBuilder().forPackages(packageName))
21 | .getSubTypesOf(DomainDeclaration::class.java)
22 | .map {
23 | val newInstance = Class.forName(it.name).getDeclaredConstructor().newInstance() as DomainDeclaration
24 | cachedDomains[newInstance.domainName] = newInstance
25 | }
26 |
27 | return cachedDomains
28 | }
29 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/SupportedDomains.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains
2 |
3 | import com.fasterxml.jackson.annotation.JsonValue
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | enum class SupportedDomains(@JsonValue val value: String) {
8 | Frontend("frontend"),
9 | CodeInterpreter("code-interpreter"),
10 | Testcase("testcase"),
11 | SQL("sql"),
12 | Spec("spec"),
13 | CodeSemanticSearch("semantic-search"),
14 | Custom("custom"),
15 | ;
16 | }
17 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/frontend/FEDomainDecl.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.frontend
2 |
3 | import cc.unitmesh.cf.core.flow.DomainDeclaration
4 | import cc.unitmesh.cf.core.flow.Workflow
5 | import org.springframework.stereotype.Component
6 |
7 | @Component
8 | class FEDomainDecl : DomainDeclaration {
9 | override val domainName: String get() = "frontend"
10 | override val description: String get() = "设计前端 UI,生成前端代码、组件等"
11 |
12 | override fun workflow(question: String): Workflow {
13 | return FEWorkflow()
14 | }
15 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/frontend/context/FEContext.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.frontend.context
2 |
3 | import cc.unitmesh.cf.core.context.DslContext
4 |
5 | /**
6 | * TODO: use Knowledge-base to find related components
7 | * 1. use OpenAI to generate related components
8 | * 2. use Knowledge-base to find related components
9 | */
10 | class FrontendDslContext(
11 | private val similarLayouts: List,
12 | private val relatedComponents: List,
13 | ) : DslContext(nearestInterpreters = listOf(), chatHistories = "") {
14 | override fun compileVariable(text: String): String {
15 | return text
16 | .replace("{layouts}", similarLayouts.joinToString(separator = ","))
17 | .replace("{components}", relatedComponents.joinToString(separator = ","))
18 | }
19 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/frontend/context/FEDslContextBuilder.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.frontend.context
2 |
3 | import cc.unitmesh.cf.core.context.DslContext
4 | import cc.unitmesh.cf.core.context.DslContextBuilder
5 | import cc.unitmesh.cf.core.dsl.InterpreterContext
6 | import cc.unitmesh.cf.infrastructure.cache.CachedEmbeddingService
7 | import cc.unitmesh.nlp.similarity.JaccardSimilarity
8 | import org.springframework.stereotype.Component
9 |
10 | @Component
11 | class FEDslContextBuilder(
12 | cachedEmbedding: CachedEmbeddingService,
13 | ) : DslContextBuilder(JaccardSimilarity(), cachedEmbedding) {
14 | override fun buildFor(domain: InterpreterContext, question: String, chatHistories: String): DslContext {
15 | return FrontendDslContext(
16 | similarLayouts = listOf(),
17 | relatedComponents = listOf(),
18 | )
19 | }
20 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/frontend/context/FEVariables.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.frontend.context
2 |
3 | data class FEVariables(
4 | val question: String,
5 | val histories: List,
6 | val layouts: String,
7 | val components: String,
8 | )
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/interpreter/CodeInterpreter.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.interpreter
2 |
3 | import cc.unitmesh.cf.core.dsl.Dsl
4 | import cc.unitmesh.cf.core.dsl.Interpreter
5 | import cc.unitmesh.cf.domains.SupportedDomains
6 | import cc.unitmesh.code.interpreter.KotlinInterpreter
7 | import cc.unitmesh.code.interpreter.api.InterpreterRequest
8 | import cc.unitmesh.code.messaging.Message
9 | import org.springframework.stereotype.Component
10 |
11 | @Component
12 | class CodeInterpreter : Interpreter {
13 | val repl: KotlinInterpreter = KotlinInterpreter()
14 | override fun canInterpret(dsl: Dsl): Boolean {
15 | return dsl.domain == SupportedDomains.CodeInterpreter.value
16 | }
17 |
18 | override fun interpret(dsl: Dsl): Message {
19 | return repl.eval(InterpreterRequest(code = dsl.content))
20 | }
21 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/interpreter/CodeInterpreterDomainDecl.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.interpreter
2 |
3 | import cc.unitmesh.cf.core.flow.DomainDeclaration
4 | import cc.unitmesh.cf.core.flow.Workflow
5 | import cc.unitmesh.cf.domains.SupportedDomains
6 | import org.springframework.stereotype.Component
7 |
8 | @Component
9 | class CodeInterpreterDomainDecl : DomainDeclaration {
10 | override val domainName: String get() = SupportedDomains.CodeInterpreter.value
11 | override val description: String get() = "生成和执行 Kotlin 代码,如生成 API、绘图等。"
12 |
13 | override fun workflow(question: String): Workflow {
14 | return CodeInterpreterWorkflow()
15 | }
16 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/semantic/CodeSemanticDecl.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.semantic
2 |
3 | import cc.unitmesh.cf.core.flow.DomainDeclaration
4 | import cc.unitmesh.cf.core.flow.Workflow
5 | import cc.unitmesh.cf.domains.SupportedDomains
6 | import org.springframework.stereotype.Component
7 |
8 | @Component
9 | class CodeSemanticDecl : DomainDeclaration {
10 | override val domainName: String get() = SupportedDomains.CodeSemanticSearch.value
11 | override val description: String get() = "语义化的代码搜索,以帮助你更好的理解代码库。"
12 |
13 | override fun workflow(question: String): Workflow {
14 | return CodeSemanticWorkflow()
15 | }
16 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/semantic/context/SemanticVariables.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.semantic.context
2 |
3 | class SemanticVariables(
4 | var englishQuery: String,
5 | var originLanguageQuery: String,
6 | var hypotheticalCode: String,
7 | var relevantCode: List,
8 | )
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/spec/SpecDomainDecl.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.spec
2 |
3 | import cc.unitmesh.cf.core.flow.DomainDeclaration
4 | import cc.unitmesh.cf.core.flow.Workflow
5 | import org.springframework.stereotype.Component
6 |
7 | @Component
8 | class SpecDomainDecl : DomainDeclaration {
9 | override val domainName: String get() = "spec"
10 | override val description: String get() = "查询系统相关的规范等。"
11 |
12 | override fun workflow(question: String): Workflow {
13 | return SpecWorkflow()
14 | }
15 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/spec/flow/SpecSolutionExecutor.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.spec.flow
2 |
3 | import cc.unitmesh.cf.core.dsl.Dsl
4 | import cc.unitmesh.cf.core.dsl.DslInterpreter
5 | import cc.unitmesh.cf.core.dsl.Interpreter
6 | import cc.unitmesh.cf.core.flow.SolutionExecutor
7 | import cc.unitmesh.cf.core.flow.model.Answer
8 | import cc.unitmesh.cf.core.llms.LlmProvider
9 | import io.reactivex.rxjava3.core.Flowable
10 |
11 |
12 | data class SpecLang(
13 | val words: List,
14 | override val content: String,
15 | ) : Dsl {
16 | override var domain: String = "spec"
17 | override var interpreters: List = listOf()
18 | }
19 |
20 | // TODO: add support for solution executor
21 | class SpecSolutionExecutor(
22 | private val completion: LlmProvider
23 | ): SolutionExecutor {
24 | override val interpreters: List = listOf()
25 |
26 | override fun execute(solution: SpecLang): Flowable {
27 | TODO("Not yet implemented")
28 | }
29 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/sql/SqlWorkflow.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.sql
2 |
3 | import cc.unitmesh.cf.core.flow.Workflow
4 | import cc.unitmesh.cf.core.flow.model.ChatWebContext
5 | import cc.unitmesh.cf.core.flow.model.StageContext
6 | import cc.unitmesh.cf.core.flow.model.WorkflowResult
7 | import cc.unitmesh.cf.core.llms.LlmProvider
8 | import io.reactivex.rxjava3.core.Flowable
9 | import org.springframework.beans.factory.annotation.Autowired
10 | import org.springframework.stereotype.Component
11 |
12 | @Component
13 | class SqlWorkflow() : Workflow() {
14 | @Autowired
15 | private lateinit var llmProvider: LlmProvider
16 |
17 | override fun execute(prompt: StageContext, chatWebContext: ChatWebContext): Flowable {
18 | TODO("Not yet implemented")
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/sql/domain/SqlDsl.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.sql.domain
2 |
3 | import cc.unitmesh.cf.core.dsl.Dsl
4 | import cc.unitmesh.cf.core.dsl.DslInterpreter
5 |
6 | class SqlDsl(
7 | val type: String,
8 | val views: List,
9 | val select: List,
10 | val where: List,
11 | val orderBy: List,
12 | val limit: String?,
13 | override val content: String = "",
14 | ) : Dsl {
15 | override var domain: String = ""
16 |
17 | override lateinit var interpreters: List
18 |
19 | lateinit var from: List
20 |
21 | data class Table(
22 | val description: String,
23 | val name: String = "",
24 | )
25 |
26 | data class Column(
27 | val description: String,
28 | var name: String = "",
29 | var type: String = "",
30 | )
31 |
32 | class Filter(
33 | val column: Column,
34 | var operation: String,
35 | var value: String,
36 | var alternatives: List = emptyList(),
37 | )
38 |
39 | class Sort(
40 | val column: Column,
41 | val direction: String,
42 | )
43 | }
44 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/testcase/TestcaseDomainDecl.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.testcase
2 |
3 | import cc.unitmesh.cf.core.flow.DomainDeclaration
4 | import cc.unitmesh.cf.core.flow.Workflow
5 | import org.springframework.stereotype.Component
6 |
7 | @Component
8 | class TestcaseDomainDecl : DomainDeclaration {
9 | override val domainName: String get() = DOMAIN
10 | override val description: String get() = "根据用户的输入,生成测试用例"
11 |
12 | override fun workflow(question: String): Workflow {
13 | return TestcaseWorkflow()
14 | }
15 |
16 | companion object {
17 | const val DOMAIN = "testcase"
18 | }
19 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/testcase/context/TestcaseVariableResolver.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.testcase.context
2 |
3 | import cc.unitmesh.cf.core.context.variable.VariableResolver
4 | import org.apache.velocity.VelocityContext
5 | import org.apache.velocity.app.Velocity
6 | import org.springframework.stereotype.Component
7 | import java.io.StringWriter
8 |
9 | @Component
10 | class TestcaseVariableResolver : VariableResolver {
11 | override var variables: TestcaseVariables? = TestcaseVariables(
12 | question = "",
13 | histories = listOf(),
14 | )
15 | override val velocityContext = VelocityContext()
16 |
17 | override fun resolve(question: String) {
18 | // TODO("Not yet implemented")
19 | }
20 |
21 | fun updateQuestion(question: String) {
22 | variables = variables!!.copy(question = question)
23 | }
24 |
25 | fun updateHistories(histories: List) {
26 | variables = variables!!.copy(histories = histories)
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/testcase/context/TestcaseVariables.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.testcase.context
2 |
3 | data class TestcaseVariables(
4 | val question: String,
5 | val histories: List,
6 | ) {
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/domains/testcase/model/TestcasePrinciples.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.testcase.model
2 |
3 | import cc.unitmesh.cf.core.prompt.QAExample
4 |
5 | data class TestcasePrinciples(
6 | val name: String,
7 | val description: String,
8 | val examples: List = listOf()
9 | ) {
10 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/infrastructure/cache/CachedEmbeddingService.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.infrastructure.cache
2 |
3 | import cc.unitmesh.cf.core.cache.CachableEmbedding
4 | import cc.unitmesh.nlp.embedding.Embedding
5 | import cc.unitmesh.nlp.embedding.EmbeddingProvider
6 | import cc.unitmesh.cf.infrastructure.repository.EmbeddingCacheRepository
7 | import org.springframework.stereotype.Component
8 |
9 | @Component
10 | class CachedEmbeddingService(
11 | val embeddingProvider: EmbeddingProvider,
12 | val cacheRepository: EmbeddingCacheRepository,
13 | ) : CachableEmbedding {
14 | override fun create(text: String): Embedding {
15 | val cache = EmbeddingCache(text = text, embedding = embeddingProvider.embed(text))
16 | val entry = cacheRepository.findByText(text) ?: cacheRepository.save(cache)
17 | return entry.embedding
18 | }
19 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/infrastructure/cache/EmbeddingCache.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.infrastructure.cache
2 |
3 | import cc.unitmesh.nlp.embedding.Embedding
4 | import cc.unitmesh.cf.core.utils.Constants
5 | import cc.unitmesh.cf.core.utils.IdUtil
6 | import cc.unitmesh.cf.infrastructure.cache.utils.EmbeddingConverter
7 | import javax.persistence.Column
8 | import javax.persistence.Convert
9 | import javax.persistence.Entity
10 | import javax.persistence.Id
11 |
12 | @Entity
13 | public class EmbeddingCache(
14 | @Id
15 | val id: String = IdUtil.uuid(),
16 |
17 | @Column(unique = true)
18 | val text: String,
19 |
20 | @Column(length = Constants.MAX_TOKEN_LENGTH)
21 | @Convert(converter = EmbeddingConverter::class)
22 | val embedding: Embedding,
23 | )
24 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/infrastructure/cache/utils/EmbeddingConverter.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.infrastructure.cache.utils
2 |
3 | import cc.unitmesh.nlp.embedding.Embedding
4 | import javax.persistence.AttributeConverter
5 | import javax.persistence.Converter
6 |
7 | @Converter
8 | class EmbeddingConverter : AttributeConverter {
9 | override fun convertToDatabaseColumn(attribute: Embedding?): String? {
10 | return attribute?.joinToString(separator = ",")
11 | }
12 |
13 | override fun convertToEntityAttribute(dbData: String?): Embedding? {
14 | if (dbData == null) {
15 | return null
16 | }
17 |
18 | val array = dbData.split(",").filter { it.isNotEmpty() }.toTypedArray()
19 | return array.map { it.toDouble() }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/infrastructure/llms/LlmProviderFactory.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.infrastructure.llms
2 |
3 | class LlmProviderFactory {
4 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/infrastructure/llms/completion/MockLlmProvider.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.infrastructure.llms.completion
2 |
3 | import cc.unitmesh.cf.core.llms.LlmMsg
4 | import cc.unitmesh.cf.core.llms.LlmProvider
5 | import io.reactivex.rxjava3.core.Flowable
6 |
7 | class MockLlmProvider : LlmProvider {
8 | override var temperature: Double = 0.0
9 |
10 | override fun completion(messages: List): String {
11 | return ""
12 | }
13 |
14 | override fun streamCompletion(messages: List): Flowable {
15 | TODO("Not yet implemented")
16 | }
17 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/infrastructure/llms/completion/OpenAiCompletionService.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.infrastructure.llms.completion
2 |
3 | import cc.unitmesh.cf.core.llms.LlmMsg
4 | import cc.unitmesh.cf.core.llms.LlmProvider
5 | import cc.unitmesh.cf.infrastructure.llms.configuration.OpenAiConfiguration
6 | import cc.unitmesh.openai.OpenAiProvider
7 | import io.reactivex.rxjava3.core.Flowable
8 | import org.springframework.stereotype.Component
9 |
10 | @Component
11 | class OpenAiCompletionService(val config: OpenAiConfiguration) : LlmProvider {
12 | val provider = OpenAiProvider(config.apiKey, config.apiHost)
13 | override var temperature: Double = 0.0
14 |
15 | override fun completion(messages: List): String {
16 | return provider.completion(messages)
17 | }
18 |
19 | override fun streamCompletion(messages: List): Flowable {
20 | return provider.streamCompletion(messages)
21 | }
22 |
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/infrastructure/llms/completion/model/SimpleOpenAIFormat.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.infrastructure.llms.completion.model
2 |
3 | import com.theokanning.openai.completion.chat.ChatMessage
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class SimpleOpenAIFormat(val role: String, val content: String) {
8 | companion object {
9 | fun fromChatMessage(message: ChatMessage): SimpleOpenAIFormat {
10 | return SimpleOpenAIFormat(message.role, message.content)
11 | }
12 | }
13 | }
14 |
15 | @Serializable
16 | data class SimpleOpenAIBody(val messages: List, val temperature: Double, val stream: Boolean)
17 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/infrastructure/llms/configuration/OpenAiConfiguration.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.infrastructure.llms.configuration
2 |
3 | import org.springframework.boot.context.properties.ConfigurationProperties
4 |
5 | @ConfigurationProperties(prefix = "openai")
6 | class OpenAiConfiguration {
7 | lateinit var apiKey: String
8 | var apiHost: String? = null
9 | }
10 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/infrastructure/llms/embedding/OpenAiEmbeddingService.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.infrastructure.llms.embedding
2 |
3 | import cc.unitmesh.nlp.embedding.Embedding
4 | import cc.unitmesh.nlp.embedding.EmbeddingProvider
5 | import cc.unitmesh.cf.infrastructure.llms.configuration.OpenAiConfiguration
6 | import cc.unitmesh.openai.OpenAiEmbeddingProvider
7 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
8 | import org.springframework.cache.annotation.Cacheable
9 | import org.springframework.context.annotation.Profile
10 | import org.springframework.stereotype.Component
11 |
12 | @Component
13 | @Profile("openai")
14 | @ConditionalOnProperty(prefix = "openai", name = ["api-key"])
15 | class OpenAiEmbeddingService(val config: OpenAiConfiguration) : EmbeddingProvider {
16 | val providerWrapper = OpenAiEmbeddingProvider(config.apiKey)
17 |
18 | @Cacheable("embedding")
19 | override fun embed(texts: List): List {
20 | return providerWrapper.embed(texts)
21 | }
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/infrastructure/repository/EmbeddingCacheRepository.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.infrastructure.repository
2 |
3 | import cc.unitmesh.cf.infrastructure.cache.EmbeddingCache
4 | import org.springframework.data.jpa.repository.JpaRepository
5 | import org.springframework.stereotype.Repository
6 |
7 | @Repository
8 | interface EmbeddingCacheRepository : JpaRepository {
9 | fun findByText(text: String): EmbeddingCache?
10 | }
11 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/presentation/AgentController.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.presentation
2 |
3 | import org.springframework.web.bind.annotation.*
4 |
5 | @RestController
6 | @RequestMapping("/agent")
7 | class AgentController {
8 | @PostMapping("/explain-biz")
9 | // todo: align to OpenAPI format and return Flow
10 | fun explainBiz(): String {
11 | // 1. find problem domain
12 | // 2. match problem domain to solution domain
13 | // 3. find solution domain
14 | // 4. execute solution
15 | return "TODO"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/presentation/config/WebConfig.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.presentation.config
2 |
3 | import org.springframework.context.annotation.Configuration
4 | import org.springframework.scheduling.annotation.EnableAsync
5 | import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer
6 | import org.springframework.web.servlet.config.annotation.CorsRegistry
7 | import org.springframework.web.servlet.config.annotation.EnableWebMvc
8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
9 |
10 | @Configuration
11 | @EnableWebMvc
12 | @EnableAsync
13 | class WebConfig : WebMvcConfigurer {
14 | override fun addCorsMappings(registry: CorsRegistry) {
15 | registry.addMapping("/**")
16 | .allowedMethods("*")
17 | .allowedOrigins("*")
18 | .allowedHeaders("*")
19 | }
20 |
21 | override fun configureAsyncSupport(configurer: AsyncSupportConfigurer) {
22 | configurer.setDefaultTimeout(-1)
23 | }
24 | }
--------------------------------------------------------------------------------
/server/src/main/kotlin/cc/unitmesh/cf/presentation/dto/DomainResponse.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.presentation.dto
2 |
3 | data class DomainResponse(
4 | val name: String,
5 | val description: String,
6 | )
--------------------------------------------------------------------------------
/server/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 18080
3 | servlet:
4 | context-path: /api
5 |
6 | spring:
7 | mvc:
8 | async:
9 | request-timeout: -1
10 |
11 | jpa:
12 | hibernate:
13 | ddl-auto: update
14 | show-sql: true
15 | datasource:
16 | hikari:
17 | connection-timeout: 50000
18 |
19 | elasticsearch:
20 | uris: "localhost:9200"
21 |
22 | similarity:
23 | max-result: 15
24 | min-score: 0.65
25 |
--------------------------------------------------------------------------------
/server/src/main/resources/frontend/layouts/layout-style.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "基础布局",
4 | "english": "Basic Layout",
5 | "description": "使用单一分栏创建最简单的栅格布局。",
6 | "example": "\n \n"
7 | },
8 | {
9 | "name": "分栏间隔布局",
10 | "english": "Column Gutter Layout",
11 | "description": "网页内容被分为多个列,并在这些列之间添加一些间隔或空白,以提高可读性和视觉吸引力。",
12 | "example": "\n \n \n"
13 | },
14 | {
15 | "name": "响应式布局",
16 | "english": "Responsive Layout",
17 | "description": "使网页能够适应不同尺寸和类型的设备,以提供一致的用户体验。",
18 | "example": "\n \n \n"
19 | }
20 | ]
21 |
--------------------------------------------------------------------------------
/server/src/test/kotlin/cc/unitmesh/cf/ChocolateFactoryApplicationTests.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf
2 |
3 | import org.junit.jupiter.api.Test
4 | import org.springframework.boot.test.context.SpringBootTest
5 |
6 | @SpringBootTest
7 | class ChocolateFactoryApplicationTests {
8 |
9 | @Test
10 | fun contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/server/src/test/kotlin/cc/unitmesh/cf/domains/DomainClassifyTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains
2 |
3 | import cc.unitmesh.cf.infrastructure.cache.CachedEmbeddingService
4 | import io.kotest.matchers.ints.shouldBeGreaterThanOrEqual
5 | import io.mockk.MockKAnnotations
6 | import io.mockk.impl.annotations.MockK
7 | import io.mockk.junit5.MockKExtension
8 | import org.junit.jupiter.api.BeforeEach
9 | import org.junit.jupiter.api.Test
10 | import org.junit.jupiter.api.extension.ExtendWith
11 |
12 | @ExtendWith(MockKExtension::class)
13 | class DomainClassifyTest {
14 |
15 | @MockK
16 | lateinit var cachedEmbedding: CachedEmbeddingService
17 |
18 | @BeforeEach
19 | fun setUp() = MockKAnnotations.init(this, relaxUnitFun = true) // turn relaxUnitFun on for all mocks
20 |
21 | @Test
22 | fun should_enable_lookup_domains() {
23 | val domainClassify = DomainClassify()
24 | val domain = domainClassify.lookupDomains()
25 |
26 | domain.size shouldBeGreaterThanOrEqual 1
27 | }
28 | }
--------------------------------------------------------------------------------
/server/src/test/kotlin/cc/unitmesh/cf/domains/frontend/context/FEVariableResolverTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.frontend.context
2 |
3 | import io.kotest.matchers.ints.shouldBeGreaterThan
4 | import io.kotest.matchers.shouldBe
5 | import org.junit.jupiter.api.Test
6 |
7 | class FEVariableResolverTest {
8 |
9 | @Test
10 | fun should_get_all_variables() {
11 | val resolver = FEVariableResolver()
12 | resolver.resolve("question")
13 |
14 | val compile = resolver.compile("""layouts: ${'$'}{layouts}""")
15 | compile.length shouldBeGreaterThan 0
16 | }
17 |
18 | @Test
19 | fun should_put_addition_variables() {
20 | val resolver = FEVariableResolver()
21 | resolver.resolve("question")
22 |
23 | resolver.put("test", "test")
24 |
25 | val compile = resolver.compile("""test: ${'$'}{test}""")
26 | compile shouldBe "test: test"
27 | }
28 | }
--------------------------------------------------------------------------------
/server/src/test/kotlin/cc/unitmesh/cf/domains/frontend/prompt/FEWorkflowTestController.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.frontend.prompt
2 |
3 | import cc.unitmesh.cf.domains.frontend.FEWorkflow
4 | import org.junit.jupiter.api.Test
5 |
6 | class FEWorkflowTestController {
7 |
8 | @Test
9 | fun should_return_pure_text_for_testing_in_gui() {
10 | println(FEWorkflow.CLARIFY.format())
11 | println(FEWorkflow.DESIGN.format())
12 | println(FEWorkflow.EXECUTE.format())
13 | }
14 | }
--------------------------------------------------------------------------------
/server/src/test/kotlin/cc/unitmesh/cf/domains/interpreter/CodeInterpreterWorkflowTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.interpreter
2 |
3 | import org.junit.jupiter.api.Test
4 |
5 | class CodeInterpreterWorkflowTest {
6 |
7 | @Test
8 | fun should_return_continue_action_and_ask_content() {
9 | // when
10 | val result = CodeInterpreterWorkflow.EXECUTE.format()
11 |
12 | println(result)
13 | }
14 | }
--------------------------------------------------------------------------------
/server/src/test/kotlin/cc/unitmesh/cf/domains/semantic/CodeSemanticWorkflowTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.semantic
2 |
3 | import kotlin.test.Test
4 |
5 | class CodeSemanticWorkflowTest {
6 | @Test
7 | fun should_output_analysis_prompt_for_testing() {
8 | val context = CodeSemanticWorkflow.ANALYSIS
9 | println(context.format())
10 | }
11 | }
--------------------------------------------------------------------------------
/server/src/test/kotlin/cc/unitmesh/cf/domains/testcase/TestcaseWorkflowTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.domains.testcase
2 |
3 | import org.junit.jupiter.api.Test
4 |
5 | class TestcaseWorkflowTest {
6 | @Test
7 | fun should_output_prompt_for_testing() {
8 | println(TestcaseWorkflow.ANALYZE.format());
9 | }
10 | }
--------------------------------------------------------------------------------
/server/src/test/kotlin/cc/unitmesh/cf/infrastructure/llms/completion/OpenAiCompletionServiceTest.kt:
--------------------------------------------------------------------------------
1 | package cc.unitmesh.cf.infrastructure.llms.completion
2 |
3 | import cc.unitmesh.cf.infrastructure.llms.configuration.OpenAiConfiguration
4 | import cc.unitmesh.cf.core.llms.LlmMsg
5 | import org.junit.jupiter.api.Disabled
6 |
7 | class OpenAiCompletionServiceTest {
8 | @org.junit.jupiter.api.Test
9 | @Disabled
10 | fun createCompletions() {
11 | val config = OpenAiConfiguration()
12 | config.apiKey = ""
13 | config.apiHost = ""
14 | val provider = OpenAiCompletionService(config)
15 | val chatChoices = provider.completion(listOf(LlmMsg.ChatMessage(LlmMsg.ChatRole.User, "你好")))
16 | println(chatChoices)
17 | }
18 | }
--------------------------------------------------------------------------------
/server/src/test/resources/application.yml:
--------------------------------------------------------------------------------
1 | openai:
2 | api-host: https://api.openai.com/
3 | api-key: sk-xxxxxx
4 |
5 | elasticsearch:
6 | uris: "localhost:9200"
7 |
8 | similarity:
9 | max-result: 15
10 | min-score: 0.65
11 |
--------------------------------------------------------------------------------
/server/workflow-testing.http:
--------------------------------------------------------------------------------
1 | ### Clarify
2 |
3 | POST http://localhost:18080/api/chat
4 | Content-Type: application/json
5 |
6 | {
7 | "messages": [
8 | {
9 | "role": "user",
10 | "content": "编写一个商品订单详细,布局方式:响应式,其中左边是一个商品过滤条件,右边则通过分页方式展示各种商品"
11 | }
12 | ],
13 | "stage": "Clarify",
14 | "id": "F7bbmxm",
15 | "domain": "frontend"
16 | }
17 |
18 | ### Design DSL
19 | POST http://localhost:18080/api/dsl/Design
20 | Content-Type: application/json
21 |
22 | {
23 | "dsl": "--------------------------------------\n| \"home\" |\"detail\" | Button(\"Login\") |\n--------------------------------------"
24 | }
25 |
26 | ###Interpreter Eval
27 | POST http://localhost:18080/api/interpreter/eval
28 | Content-Type: application/json
29 |
30 | {
31 | "code": "System.getenv()"
32 | }
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | @file:Suppress("UnstableApiUsage")
2 |
3 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
4 |
5 | rootProject.name = "chocolate-factory"
6 |
7 | include(":server")
8 |
9 | include(":cocoa-core")
10 |
11 | include(":docs-builder")
12 |
13 | include(":dsl:design")
14 |
15 | include(":rag-modules:document")
16 | include(":rag-modules:rag-script")
17 | include(":rag-modules:store-milvus")
18 | include(":rag-modules:store-pinecone")
19 | include(":rag-modules:store-elasticsearch")
20 |
21 | include(":llm-modules:local-embedding")
22 | include(":llm-modules:openai")
23 | include(":llm-modules:connection")
24 | include(":llm-modules:prompt-script")
25 |
26 | include(":llm-modules:dan-bert-tiny")
27 |
28 | include(":llm-tools:interpreter")
29 | include(":llm-tools:web-tools")
30 |
31 | include(":code-modules:code-splitter")
32 | include(":code-modules:code-language")
33 | include(":code-modules:git-differ")
34 | include(":code-modules:git-commit-message")
35 | include(":code-modules:api-tool-parser")
36 |
37 | dependencyResolutionManagement {
38 | repositories {
39 | mavenCentral()
40 | mavenLocal()
41 | }
42 | }
43 |
44 |
--------------------------------------------------------------------------------