Merge branch 'main' into error-state-#484

pull/532/head
Alex 9 months ago committed by GitHub
commit 3e2055255e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -24,7 +24,7 @@ Say goodbye to time-consuming manual searches, and let <strong><a href="https://
### Production Support / Help for companies:
We're eager to provide personalized assistance when deploying your DocsGPT to a live environment.
- [Get Support 👋](https://airtable.com/appdeaL0F1qV8Bl2C/shrrJF1Ll7btCJRbP)
- [Get Support 👋](https://cal.com/arc53/docsgpt-demo-b2b)
- [Send Email ✉️](mailto:contact@arc53.com?subject=DocsGPT%20support%2Fsolutions)
### [🎉 Join the Hacktoberfest with DocsGPT and Earn a Free T-shirt! 🎉](https://github.com/arc53/DocsGPT/blob/main/HACKTOBERFEST.md)
@ -54,17 +54,20 @@ If you don't have enough resources to run it, you can use bitsnbytes to quantize
## Useful links
[Live preview](https://docsgpt.arc53.com/)
- 🔍🔥 [Live preview](https://docsgpt.arc53.com/)
[Join our Discord](https://discord.gg/n5BX8dh8rU)
- 💬🎉[Join our Discord](https://discord.gg/n5BX8dh8rU)
[Guides](https://docs.docsgpt.co.uk/)
- 📚😎 [Guides](https://docs.docsgpt.co.uk/)
- 👩‍💻👨‍💻 [Interested in contributing?](https://github.com/arc53/DocsGPT/blob/main/CONTRIBUTING.md)
- 🗂️🚀 [How to use any other documentation](https://docs.docsgpt.co.uk/Guides/How-to-train-on-other-documentation)
[Interested in contributing?](https://github.com/arc53/DocsGPT/blob/main/CONTRIBUTING.md)
- 🏠🔐 [How to host it locally (so all data will stay on-premises)](https://docs.docsgpt.co.uk/Guides/How-to-use-different-LLM)
[How to use any other documentation](https://docs.docsgpt.co.uk/Guides/How-to-train-on-other-documentation)
[How to host it locally (so all data will stay on-premises)](https://docs.docsgpt.co.uk/Guides/How-to-use-different-LLM)
## Project structure

@ -53,6 +53,15 @@ def get_single_conversation():
conversation = conversations_collection.find_one({"_id": ObjectId(conversation_id)})
return jsonify(conversation['queries'])
@user.route("/api/update_conversation_name", methods=["POST"])
def update_conversation_name():
# update data for a conversation
data = request.get_json()
id = data["id"]
name = data["name"]
conversations_collection.update_one({"_id": ObjectId(id)},{"$set":{"name":name}})
return {"status": "ok"}
@user.route("/api/feedback", methods=["POST"])
def api_feedback():

@ -21,8 +21,7 @@ except FileExistsError:
def metadata_from_filename(title):
store = title.split('/')
store = store[1] + '/' + store[2]
store = '/'.join(title.split('/')[1:3])
return {'title': title, 'store': store}

@ -104,7 +104,7 @@ fetch("http://localhost:5001/api/task_status?task_id=b2d2a0f4-387c-44fd-a443-e4f
Responses:
There are two types of responses:
1. While task is still running, where "current" will show progress from 0 to 100
1. While task is still running, where "current" will show progress from 0 to 100:
```json
{
"result": {
@ -114,7 +114,7 @@ There are two types of responses:
}
```
2. When task is completed
2. When task is completed:
```json
{
"result": {
@ -133,7 +133,7 @@ There are two types of responses:
```
### /api/delete_old
Deletes old vectorstores:
Deletes old Vector stores:
```js
// Task status (GET http://127.0.0.1:5000/api/docs_check)
fetch("http://localhost:5001/api/task_status?task_id=b2d2a0f4-387c-44fd-a443-e4fe2e7454d1", {

@ -21,9 +21,13 @@ By default, we use OpenAI's models but if you want to change it or even run it l
You don't need to provide keys if you are happy with users providing theirs, so make sure you set `LLM_NAME` and `EMBEDDINGS_NAME`.
Options:
LLM_NAME (openai, manifest, cohere, Arc53/docsgpt-14b, Arc53/docsgpt-7b-falcon)
LLM_NAME (openai, manifest, cohere, Arc53/docsgpt-14b, Arc53/docsgpt-7b-falcon, llama.cpp)
EMBEDDINGS_NAME (openai_text-embedding-ada-002, huggingface_sentence-transformers/all-mpnet-base-v2, huggingface_hkunlp/instructor-large, cohere_medium)
If using Llama, set the `EMBEDDINGS_NAME` to `huggingface_sentence-transformers/all-mpnet-base-v2` and be sure to download [this model](https://d3dg1063dc54p9.cloudfront.net/models/docsgpt-7b-f16.gguf) into the `models/` folder: `https://d3dg1063dc54p9.cloudfront.net/models/docsgpt-7b-f16.gguf`.
Alternatively, if you wish to run Llama locally, you can run `setup.sh` and choose option 1 when prompted. You do not need to manually add the DocsGPT model mentioned above to your `models/` folder if you use `setup.sh`, as the script will manage that step for you.
That's it!
### Hosting everything locally and privately (for using our optimised open-source models)

@ -1,10 +1,10 @@
If your AI uses external knowledge and is not explicit enough, it is ok, because we try to make docsgpt friendly.
If your AI uses external knowledge and is not explicit enough, it is ok, because we try to make DocsGPT friendly.
But if you want to adjust it, here is a simple way.
But if you want to adjust it, here is a simple way:-
Got to `application/prompts/chat_combine_prompt.txt`
- Got to `application/prompts/chat_combine_prompt.txt`
And change it to
- And change it to
```

@ -4,7 +4,7 @@
export default function About() {
return (
<div className="mx-5 grid min-h-screen md:mx-36">
<article className="place-items-left mx-auto my-auto flex w-full max-w-6xl flex-col gap-6 rounded-3xl bg-gray-100 p-6 mt-20 text-jet lg:p-10 xl:p-16">
<article className="place-items-left mx-auto my-auto mt-20 flex w-full max-w-6xl flex-col gap-6 rounded-3xl bg-gray-100 p-6 text-jet lg:p-10 xl:p-16">
<div className="flex items-center">
<p className="mr-2 text-3xl">About DocsGPT</p>
<p className="text-[21px]">🦖</p>

@ -18,9 +18,7 @@ export default function App() {
<div
className={`transition-all duration-200 ${
!isMobile
? `ml-0 ${
!navOpen ? '-mt-5 md:mx-auto lg:mx-auto' : 'md:ml-72'
}`
? `ml-0 ${!navOpen ? '-mt-5 md:mx-auto lg:mx-auto' : 'md:ml-72'}`
: 'ml-0 md:ml-16'
}`}
>

@ -32,6 +32,7 @@ import { useMediaQuery, useOutsideAlerter } from './hooks';
import Upload from './upload/Upload';
import { Doc, getConversations } from './preferences/preferenceApi';
import SelectDocsModal from './preferences/SelectDocsModal';
import ConversationTile from './conversation/ConversationTile';
interface NavigationProps {
navOpen: boolean;
@ -68,16 +69,20 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
useEffect(() => {
if (!conversations) {
getConversations()
.then((fetchedConversations) => {
dispatch(setConversations(fetchedConversations));
})
.catch((error) => {
console.error('Failed to fetch conversations: ', error);
});
fetchConversations();
}
}, [conversations, dispatch]);
async function fetchConversations() {
return await getConversations()
.then((fetchedConversations) => {
dispatch(setConversations(fetchedConversations));
})
.catch((error) => {
console.error('Failed to fetch conversations: ', error);
});
}
const handleDeleteConversation = (id: string) => {
fetch(`${apiHost}/api/delete_conversation?id=${id}`, {
method: 'POST',
@ -89,6 +94,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
) as HTMLElement;
const parentElement = imageElement.parentNode as HTMLElement;
parentElement.parentNode?.removeChild(parentElement);
fetchConversations();
})
.catch((error) => console.error(error));
};
@ -126,6 +132,29 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
);
});
};
async function updateConversationName(updatedConversation: {
name: string;
id: string;
}) {
await fetch(`${apiHost}/api/update_conversation_name`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(updatedConversation),
})
.then((response) => response.json())
.then((data) => {
if (data) {
navigate('/');
fetchConversations();
}
})
.catch((err) => {
console.error(err);
});
}
useOutsideAlerter(
navRef,
() => {
@ -210,41 +239,17 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
</NavLink>
<div className="conversations-container max-h-[25rem] overflow-y-auto">
{conversations
? conversations.map((conversation) => {
return (
<div
key={conversation.id}
onClick={() => {
handleConversationClick(conversation.id);
}}
className={`my-auto mx-4 mt-4 flex h-12 cursor-pointer items-center justify-between gap-4 rounded-3xl hover:bg-gray-100 ${
conversationId === conversation.id ? 'bg-gray-100' : ''
}`}
>
<div className="flex gap-4">
<img src={Message} className="ml-2 w-5"></img>
<p className="my-auto text-eerie-black">
{conversation.name.length > 45
? conversation.name.substring(0, 45) + '...'
: conversation.name}
</p>
</div>
{conversationId === conversation.id ? (
<img
src={Exit}
alt="Exit"
className="mr-4 h-3 w-3 cursor-pointer hover:opacity-50"
id={`img-${conversation.id}`}
onClick={(event) => {
event.stopPropagation();
handleDeleteConversation(conversation.id);
}}
/>
) : null}
</div>
);
})
? conversations.map((conversation, index) => (
<ConversationTile
key={index}
conversation={conversation}
selectConversation={(id) => handleConversationClick(id)}
onDeleteConversation={(id) => handleDeleteConversation(id)}
onSave={(conversation) =>
updateConversationName(conversation)
}
/>
))
: null}
</div>

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="11" viewBox="0 0 14 11" fill="none">
<path d="M4.95919 10.1906C4.84318 10.1902 4.72847 10.166 4.62222 10.1194C4.51596 10.0729 4.42041 10.0049 4.34152 9.91985L0.229353 5.54538C0.0756344 5.38157 -0.00671208 5.1634 0.000428491 4.93886C0.00756906 4.71433 0.103612 4.50183 0.267428 4.34812C0.431245 4.1944 0.649417 4.11205 0.873948 4.11919C1.09848 4.12633 1.31098 4.22238 1.4647 4.38619L4.95073 8.10068L12.0666 0.316329C12.1389 0.226405 12.2287 0.152193 12.3306 0.0982513C12.4326 0.0443098 12.5445 0.0117775 12.6594 0.00265255C12.7744 -0.00647237 12.89 0.00800286 12.9992 0.045189C13.1084 0.082375 13.2088 0.141487 13.2943 0.218894C13.3798 0.296301 13.4485 0.390369 13.4964 0.49532C13.5442 0.600272 13.57 0.713891 13.5723 0.829198C13.5746 0.944506 13.5534 1.05907 13.5098 1.16585C13.4662 1.27263 13.4012 1.36937 13.3189 1.45014L5.58533 9.91139C5.50718 9.998 5.41197 10.0675 5.30567 10.1156C5.19938 10.1636 5.0843 10.1892 4.96766 10.1906H4.95919Z" fill="#747474"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -1,3 +1,3 @@
<svg width="14" height="10" viewBox="0 0 14 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.7617 1.34847L5.14891 9.76785C5.0739 9.84143 4.98476 9.89982 4.88661 9.93965C4.78847 9.97949 4.68324 10 4.57697 10C4.4707 10 4.36547 9.97949 4.26732 9.93965C4.16917 9.89982 4.08004 9.84143 4.00502 9.76785L0.236908 6.08437C0.161799 6.01095 0.102219 5.92378 0.0615703 5.82785C0.0209216 5.73192 1.11921e-09 5.6291 0 5.52527C-1.11921e-09 5.42143 0.0209216 5.31862 0.0615703 5.22269C0.102219 5.12676 0.161799 5.03959 0.236908 4.96617C0.312017 4.89275 0.401184 4.83451 0.499319 4.79477C0.597453 4.75503 0.702634 4.73458 0.808854 4.73458C0.915074 4.73458 1.02025 4.75503 1.11839 4.79477C1.21652 4.83451 1.30569 4.89275 1.3808 4.96617L4.57764 8.09121L12.6192 0.231586C12.7709 0.083304 12.9766 0 13.1911 0C13.4057 0 13.6114 0.083304 13.7631 0.231586C13.9148 0.379869 14 0.580983 14 0.790686C14 1.00039 13.9148 1.2015 13.7631 1.34978L13.7617 1.34847Z" fill="#13A10E"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="11" viewBox="0 0 14 11" fill="none">
<path d="M4.95919 10.1906C4.84318 10.1902 4.72847 10.166 4.62222 10.1194C4.51596 10.0729 4.42041 10.0049 4.34152 9.91985L0.229353 5.54538C0.0756344 5.38157 -0.00671208 5.1634 0.000428491 4.93886C0.00756906 4.71433 0.103612 4.50183 0.267428 4.34812C0.431245 4.1944 0.649417 4.11205 0.873948 4.11919C1.09848 4.12633 1.31098 4.22238 1.4647 4.38619L4.95073 8.10068L12.0666 0.316329C12.1389 0.226405 12.2287 0.152193 12.3306 0.0982513C12.4326 0.0443098 12.5445 0.0117775 12.6594 0.00265255C12.7744 -0.00647237 12.89 0.00800286 12.9992 0.045189C13.1084 0.082375 13.2088 0.141487 13.2943 0.218894C13.3798 0.296301 13.4485 0.390369 13.4964 0.49532C13.5442 0.600272 13.57 0.713891 13.5723 0.829198C13.5746 0.944506 13.5534 1.05907 13.5098 1.16585C13.4662 1.27263 13.4012 1.36937 13.3189 1.45014L5.58533 9.91139C5.50718 9.998 5.41197 10.0675 5.30567 10.1156C5.19938 10.1636 5.0843 10.1892 4.96766 10.1906H4.95919Z" fill="#747474"/>
</svg>

Before

Width:  |  Height:  |  Size: 974 B

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="15" viewBox="0 0 16 15" fill="none">
<path d="M10.0588 2.74568L12.5294 5.15732M8.41176 14H15M1.82353 10.7845L1 14L4.29412 13.1961L13.8355 3.88237C14.1443 3.58087 14.3178 3.172 14.3178 2.74568C14.3178 2.31936 14.1443 1.9105 13.8355 1.609L13.6939 1.47073C13.385 1.16932 12.9662 1 12.5294 1C12.0927 1 11.6738 1.16932 11.3649 1.47073L1.82353 10.7845Z" stroke="#747474" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 500 B

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="15" viewBox="0 0 12 15" fill="none">
<path d="M0.857143 13.3333C0.857143 13.7754 1.03775 14.1993 1.35925 14.5118C1.68074 14.8244 2.11677 15 2.57143 15H9.42857C9.88323 15 10.3193 14.8244 10.6408 14.5118C10.9622 14.1993 11.1429 13.7754 11.1429 13.3333V3.33333H0.857143V13.3333ZM2.57143 5H9.42857V13.3333H2.57143V5ZM9 0.833333L8.14286 0H3.85714L3 0.833333H0V2.5H12V0.833333H9Z" fill="#747474"/>
</svg>

After

Width:  |  Height:  |  Size: 459 B

@ -74,7 +74,7 @@ const ConversationBubble = forwardRef<
<div className="flex self-start">
<Avatar className="mt-2 text-2xl" avatar="🦖"></Avatar>
<div
className={`ml-2 mr-5 flex items-center bg-gray-1000 p-3.5 ${
className={`ml-2 mr-5 flex flex-col items-center rounded-3xl bg-gray-1000 p-3.5 ${
type === 'ERROR'
? 'flex-row rounded-full border border-transparent bg-[#FFE7E7] p-2 py-5 text-sm font-normal text-red-3000 dark:border-red-2000 dark:text-white'
: 'flex-col rounded-3xl'
@ -84,7 +84,7 @@ const ConversationBubble = forwardRef<
<img src={Alert} alt="alert" className="mr-2 inline" />
)}
<ReactMarkdown
className="whitespace-pre-wrap break-words"
className="max-w-screen-md whitespace-pre-wrap break-words"
components={{
code({ node, inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || '');

@ -0,0 +1,128 @@
import { useEffect, useRef, useState } from 'react';
import { useSelector } from 'react-redux';
import Edit from '../assets/edit.svg';
import Exit from '../assets/exit.svg';
import Message from '../assets/message.svg';
import CheckMark from '../assets/checkmark.svg';
import Trash from '../assets/trash.svg';
import { selectConversationId } from '../preferences/preferenceSlice';
import { useOutsideAlerter } from '../hooks';
interface ConversationProps {
name: string;
id: string;
}
interface ConversationTileProps {
conversation: ConversationProps;
selectConversation: (arg1: string) => void;
onDeleteConversation: (arg1: string) => void;
onSave: ({ name, id }: ConversationProps) => void;
}
export default function ConversationTile({
conversation,
selectConversation,
onDeleteConversation,
onSave,
}: ConversationTileProps) {
const conversationId = useSelector(selectConversationId);
const tileRef = useRef<HTMLInputElement>(null);
const [isEdit, setIsEdit] = useState(false);
const [conversationName, setConversationsName] = useState('');
useOutsideAlerter(
tileRef,
() =>
handleSaveConversation({
id: conversationId || conversation.id,
name: conversationName,
}),
[conversationName],
);
useEffect(() => {
setConversationsName(conversation.name);
}, [conversation.name]);
function handleEditConversation() {
setIsEdit(true);
}
function handleSaveConversation(changedConversation: ConversationProps) {
if (changedConversation.name.trim().length) {
onSave(changedConversation);
setIsEdit(false);
} else {
onClear();
}
}
function onClear() {
setConversationsName(conversation.name);
setIsEdit(false);
}
return (
<div
ref={tileRef}
onClick={() => {
selectConversation(conversation.id);
}}
className={`my-auto mx-4 mt-4 flex h-12 cursor-pointer items-center justify-between gap-4 rounded-3xl hover:bg-gray-100 ${
conversationId === conversation.id ? 'bg-gray-100' : ''
}`}
>
<div
className={`flex ${
conversationId === conversation.id ? 'w-[75%]' : 'w-[95%]'
} gap-4`}
>
<img src={Message} className="ml-2 w-5"></img>
{isEdit ? (
<input
autoFocus
type="text"
className="h-6 w-full px-1 text-sm font-normal leading-6 outline-[#0075FF] focus:outline-1"
value={conversationName}
onChange={(e) => setConversationsName(e.target.value)}
/>
) : (
<p className="my-auto overflow-hidden overflow-ellipsis whitespace-nowrap text-sm font-normal leading-6 text-eerie-black">
{conversationName}
</p>
)}
</div>
{conversationId === conversation.id ? (
<div className="flex">
<img
src={isEdit ? CheckMark : Edit}
alt="Edit"
className="mr-2 h-4 w-4 cursor-pointer hover:opacity-50"
id={`img-${conversation.id}`}
onClick={(event) => {
event.stopPropagation();
isEdit
? handleSaveConversation({
id: conversationId,
name: conversationName,
})
: handleEditConversation();
}}
/>
<img
src={isEdit ? Exit : Trash}
alt="Exit"
className={`mr-4 ${
isEdit ? 'h-3 w-3' : 'h-4 w-4'
}mt-px cursor-pointer hover:opacity-50`}
id={`img-${conversation.id}`}
onClick={(event) => {
event.stopPropagation();
isEdit ? onClear() : onDeleteConversation(conversation.id);
}}
/>
</div>
) : null}
</div>
);
}

@ -78,14 +78,12 @@ def ingest(yes: bool = typer.Option(False, "-y", "--yes", prompt=False,
# Here we check for command line arguments for bot calls.
# If no argument exists or the yes is not True, then the
# user permission is requested to call the API.
if len(sys.argv) > 1:
if yes:
call_openai_api(docs, folder_name)
else:
get_user_permission(docs, folder_name)
if len(sys.argv) > 1 and yes:
call_openai_api(docs, folder_name)
else:
get_user_permission(docs, folder_name)
folder_counts = defaultdict(int)
folder_names = []
for dir_path in dir:
@ -110,14 +108,19 @@ def convert(dir: Optional[str] = typer.Option("inputs",
Creates documentation linked to original functions from specified location.
By default /inputs folder is used, .py is parsed.
"""
if formats == 'py':
functions_dict, classes_dict = extract_py(dir)
elif formats == 'js':
functions_dict, classes_dict = extract_js(dir)
elif formats == 'java':
functions_dict, classes_dict = extract_java(dir)
# Using a dictionary to map between the formats and their respective extraction functions
# makes the code more scalable. When adding more formats in the future,
# you only need to update the extraction_functions dictionary.
extraction_functions = {
'py': extract_py,
'js': extract_js,
'java': extract_java
}
if formats in extraction_functions:
functions_dict, classes_dict = extraction_functions[formats](dir)
else:
raise Exception("Sorry, language not supported yet")
raise Exception("Sorry, language not supported yet")
transform_to_docs(functions_dict, classes_dict, formats, dir)

Loading…
Cancel
Save